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 
12*2f3df613SZachary Turner #include "lldb/Breakpoint/Breakpoint.h" // for Breakpoint, Brea...
13*2f3df613SZachary Turner #include "lldb/Core/Event.h"            // for Event, EventData...
14554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h"
15*2f3df613SZachary Turner #include "lldb/Core/Listener.h" // for Listener
16*2f3df613SZachary Turner #include "lldb/Core/Mangled.h"  // for Mangled
17e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h"
1830fdc8d8SChris Lattner #include "lldb/Core/State.h"
195b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h"
2044d93782SGreg Clayton #include "lldb/Core/StreamFile.h"
215548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h"
223e7e915dSSean Callanan #include "lldb/Expression/REPL.h"
23*2f3df613SZachary Turner #include "lldb/Host/File.h" // for File, File::kInv...
2442ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h"
25a3406614SGreg Clayton #include "lldb/Host/Terminal.h"
2639de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h"
276611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h"
28*2f3df613SZachary Turner #include "lldb/Interpreter/OptionValue.h" // for OptionValue, Opt...
29633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h"
3067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h"
3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h"
32*2f3df613SZachary Turner #include "lldb/Interpreter/Property.h"          // for PropertyDefinition
33*2f3df613SZachary Turner #include "lldb/Interpreter/ScriptInterpreter.h" // for ScriptInterpreter
341f746071SGreg Clayton #include "lldb/Symbol/Function.h"
351f746071SGreg Clayton #include "lldb/Symbol/Symbol.h"
36*2f3df613SZachary Turner #include "lldb/Symbol/SymbolContext.h" // for SymbolContext
373e7e915dSSean Callanan #include "lldb/Target/Language.h"
3830fdc8d8SChris Lattner #include "lldb/Target/Process.h"
3975930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h"
4084a53dfbSEnrico Granata #include "lldb/Target/Target.h"
41b9c1b51eSKate Stone #include "lldb/Target/TargetList.h"
4230fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
43*2f3df613SZachary Turner #include "lldb/Target/ThreadList.h" // for ThreadList
445a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h"
45*2f3df613SZachary Turner #include "lldb/Utility/Log.h"    // for LLDB_LOG_OPTION_...
46*2f3df613SZachary Turner #include "lldb/Utility/Stream.h" // for Stream
47fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h"
48bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
49*2f3df613SZachary Turner 
50*2f3df613SZachary Turner #if defined(LLVM_ON_WIN32)
51*2f3df613SZachary Turner #include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
52*2f3df613SZachary Turner #endif
53*2f3df613SZachary Turner 
54*2f3df613SZachary Turner #include "llvm/ADT/None.h"      // for None
55*2f3df613SZachary Turner #include "llvm/ADT/STLExtras.h" // for make_unique
56*2f3df613SZachary Turner #include "llvm/ADT/StringRef.h"
57*2f3df613SZachary Turner #include "llvm/ADT/iterator.h" // for iterator_facade_...
58*2f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h"
59*2f3df613SZachary Turner #include "llvm/Support/FileSystem.h"
60*2f3df613SZachary Turner #include "llvm/Support/Threading.h"
61*2f3df613SZachary Turner #include "llvm/Support/raw_ostream.h" // for raw_fd_ostream
62*2f3df613SZachary Turner 
63*2f3df613SZachary Turner #include <list>   // for list
64*2f3df613SZachary Turner #include <memory> // for make_shared
65*2f3df613SZachary Turner #include <mutex>
66*2f3df613SZachary Turner #include <set>          // for set
67*2f3df613SZachary Turner #include <stdio.h>      // for size_t, NULL
68*2f3df613SZachary Turner #include <stdlib.h>     // for getenv
69*2f3df613SZachary Turner #include <string.h>     // for strcmp
70*2f3df613SZachary Turner #include <string>       // for string
71*2f3df613SZachary Turner #include <system_error> // for error_code
72*2f3df613SZachary Turner 
73*2f3df613SZachary Turner namespace lldb_private {
74*2f3df613SZachary Turner class Address;
75*2f3df613SZachary Turner }
7630fdc8d8SChris Lattner 
7730fdc8d8SChris Lattner using namespace lldb;
7830fdc8d8SChris Lattner using namespace lldb_private;
7930fdc8d8SChris Lattner 
80ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1;
817c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024;
82ebc1bb27SCaroline Tice 
831b654882SGreg Clayton #pragma mark Static Functions
841b654882SGreg Clayton 
851b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList;
86b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr =
87b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
88b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr =
89b9c1b51eSKate Stone     nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
90e372b98dSGreg Clayton 
91b9c1b51eSKate Stone OptionEnumValueElement g_show_disassembly_enum_values[] = {
92b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNever, "never",
93b9c1b51eSKate Stone      "Never show disassembly when displaying a stop context."},
94b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
95b9c1b51eSKate Stone      "Show disassembly when there is no debug information."},
96b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeNoSource, "no-source",
97b9c1b51eSKate Stone      "Show disassembly when there is no source information, or the source file "
98b9c1b51eSKate Stone      "is missing when displaying a stop context."},
99b9c1b51eSKate Stone     {Debugger::eStopDisassemblyTypeAlways, "always",
100b9c1b51eSKate Stone      "Always show disassembly when displaying a stop context."},
101b9c1b51eSKate Stone     {0, nullptr, nullptr}};
102e372b98dSGreg Clayton 
103b9c1b51eSKate Stone OptionEnumValueElement g_language_enumerators[] = {
10467cc0636SGreg Clayton     {eScriptLanguageNone, "none", "Disable scripting languages."},
105b9c1b51eSKate Stone     {eScriptLanguagePython, "python",
106b9c1b51eSKate Stone      "Select python as the default scripting language."},
107b9c1b51eSKate Stone     {eScriptLanguageDefault, "default",
108b9c1b51eSKate Stone      "Select the lldb default as the default scripting language."},
109b9c1b51eSKate Stone     {0, nullptr, nullptr}};
110e372b98dSGreg Clayton 
111b9c1b51eSKate Stone #define MODULE_WITH_FUNC                                                       \
112b9c1b51eSKate Stone   "{ "                                                                         \
1136a9767c7SJim Ingham   "${module.file.basename}{`${function.name-with-args}"                        \
1146a9767c7SJim Ingham   "{${frame.no-debug}${function.pc-offset}}}}"
11567cc0636SGreg Clayton #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
1166ab659a9SJason Molenda #define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
11767cc0636SGreg Clayton 
118b9c1b51eSKate Stone #define DEFAULT_THREAD_FORMAT                                                  \
119b9c1b51eSKate Stone   "thread #${thread.index}: tid = ${thread.id%tid}"                            \
120b9c1b51eSKate Stone   "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE                             \
1210769b2b1SMichael Sartain   "{, name = '${thread.name}'}"                                                \
1220769b2b1SMichael Sartain   "{, queue = '${thread.queue}'}"                                              \
123705b1809SJason Molenda   "{, activity = '${thread.info.activity.name}'}"                              \
124705b1809SJason Molenda   "{, ${thread.info.trace_messages} messages}"                                 \
12567cc0636SGreg Clayton   "{, stop reason = ${thread.stop-reason}}"                                    \
12667cc0636SGreg Clayton   "{\\nReturn value: ${thread.return-value}}"                                  \
12730fadafeSJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
12867cc0636SGreg Clayton   "\\n"
12967cc0636SGreg Clayton 
1306a9767c7SJim Ingham #define DEFAULT_THREAD_STOP_FORMAT                                             \
1316a9767c7SJim Ingham   "thread #${thread.index}{, name = '${thread.name}'}"                         \
1326a9767c7SJim Ingham   "{, queue = '${thread.queue}'}"                                              \
1336a9767c7SJim Ingham   "{, activity = '${thread.info.activity.name}'}"                              \
1346a9767c7SJim Ingham   "{, ${thread.info.trace_messages} messages}"                                 \
1356a9767c7SJim Ingham   "{, stop reason = ${thread.stop-reason}}"                                    \
1366a9767c7SJim Ingham   "{\\nReturn value: ${thread.return-value}}"                                  \
1376a9767c7SJim Ingham   "{\\nCompleted expression: ${thread.completed-expression}}"                  \
1386a9767c7SJim Ingham   "\\n"
1396a9767c7SJim Ingham 
140b9c1b51eSKate Stone #define DEFAULT_FRAME_FORMAT                                                   \
141270e8228SJason Molenda   "frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE          \
142b9c1b51eSKate Stone       IS_OPTIMIZED "\\n"
14367cc0636SGreg Clayton 
144c980fa92SJason Molenda // Three parts to this disassembly format specification:
145c980fa92SJason Molenda //   1. If this is a new function/symbol (no previous symbol/function), print
146c980fa92SJason Molenda //      dylib`funcname:\n
147b9c1b51eSKate Stone //   2. If this is a symbol context change (different from previous
148b9c1b51eSKate Stone //   symbol/function), print
149c980fa92SJason Molenda //      dylib`funcname:\n
150c980fa92SJason Molenda //   3. print
151c980fa92SJason Molenda //      address <+offset>:
152b9c1b51eSKate Stone #define DEFAULT_DISASSEMBLY_FORMAT                                             \
153b9c1b51eSKate Stone   "{${function.initial-function}{${module.file.basename}`}{${function.name-"   \
154b9c1b51eSKate Stone   "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${"      \
155b9c1b51eSKate Stone   "function.name-without-args}}:\n}{${current-pc-arrow} "                      \
156b9c1b51eSKate Stone   "}${addr-file-or-load}{ "                                                    \
157b9c1b51eSKate Stone   "<${function.concrete-only-addr-offset-no-padding}>}: "
158c980fa92SJason Molenda 
159c980fa92SJason Molenda // gdb's disassembly format can be emulated with
160b9c1b51eSKate Stone // ${current-pc-arrow}${addr-file-or-load}{
161b9c1b51eSKate Stone // <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}:
162c980fa92SJason Molenda 
163c980fa92SJason Molenda // lldb's original format for disassembly would look like this format string -
164b9c1b51eSKate 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}
165b9c1b51eSKate Stone // }{${addr-file-or-load}}:
166c980fa92SJason Molenda 
1679666ba75STodd Fiala #define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
1689666ba75STodd Fiala #define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
1699666ba75STodd Fiala 
1709666ba75STodd Fiala static OptionEnumValueElement s_stop_show_column_values[] = {
1719666ba75STodd Fiala     {eStopShowColumnAnsiOrCaret, "ansi-or-caret",
1729666ba75STodd Fiala      "Highlight the stop column with ANSI terminal codes when color/ANSI mode "
1739666ba75STodd Fiala      "is enabled; otherwise, fall back to using a text-only caret (^) as if "
1749666ba75STodd Fiala      "\"caret-only\" mode was selected."},
1759666ba75STodd Fiala     {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI "
1769666ba75STodd Fiala                                   "terminal codes when running LLDB with "
1779666ba75STodd Fiala                                   "color/ANSI enabled."},
1789666ba75STodd Fiala     {eStopShowColumnCaret, "caret",
1799666ba75STodd Fiala      "Highlight the stop column with a caret character (^) underneath the stop "
1809666ba75STodd Fiala      "column. This method introduces a new line in source listings that "
1819666ba75STodd Fiala      "display thread stop locations."},
1829666ba75STodd Fiala     {eStopShowColumnNone, "none", "Do not highlight the stop column."},
1839666ba75STodd Fiala     {0, nullptr, nullptr}};
1849666ba75STodd Fiala 
185b9c1b51eSKate Stone static PropertyDefinition g_properties[] = {
186b9c1b51eSKate Stone     {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
187b9c1b51eSKate Stone      "If true all confirmation prompts will receive their default reply."},
188b9c1b51eSKate Stone     {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
189b9c1b51eSKate Stone      DEFAULT_DISASSEMBLY_FORMAT, nullptr, "The default disassembly format "
190b9c1b51eSKate Stone                                           "string to use when disassembling "
191b9c1b51eSKate Stone                                           "instruction sequences."},
192b9c1b51eSKate Stone     {"frame-format", OptionValue::eTypeFormatEntity, true, 0,
193b9c1b51eSKate Stone      DEFAULT_FRAME_FORMAT, nullptr, "The default frame format string to use "
194b9c1b51eSKate Stone                                     "when displaying stack frame information "
195b9c1b51eSKate Stone                                     "for threads."},
196b9c1b51eSKate Stone     {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
197b9c1b51eSKate Stone      "Notify the user explicitly if an expression returns void (default: "
198b9c1b51eSKate Stone      "false)."},
199b9c1b51eSKate Stone     {"prompt", OptionValue::eTypeString, true,
200b9c1b51eSKate Stone      OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ",
201b9c1b51eSKate Stone      nullptr, "The debugger command line prompt displayed for the user."},
202b9c1b51eSKate Stone     {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
203b9c1b51eSKate Stone      nullptr, g_language_enumerators,
204b9c1b51eSKate Stone      "The script language to be used for evaluating user-written scripts."},
205b9c1b51eSKate Stone     {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr,
206b9c1b51eSKate Stone      nullptr, "The number of disassembly lines to show when displaying a "
207b9c1b51eSKate Stone               "stopped context."},
208b9c1b51eSKate Stone     {"stop-disassembly-display", OptionValue::eTypeEnum, true,
209b9c1b51eSKate Stone      Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
210b9c1b51eSKate Stone      g_show_disassembly_enum_values,
211b9c1b51eSKate Stone      "Control when to display disassembly when displaying a stopped context."},
212b9c1b51eSKate Stone     {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr,
213b9c1b51eSKate Stone      nullptr, "The number of sources lines to display that come after the "
214b9c1b51eSKate Stone               "current source line when displaying a stopped context."},
215b9c1b51eSKate Stone     {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr,
216b9c1b51eSKate Stone      nullptr, "The number of sources lines to display that come before the "
217b9c1b51eSKate Stone               "current source line when displaying a stopped context."},
2189666ba75STodd Fiala     {"stop-show-column", OptionValue::eTypeEnum, false,
2199666ba75STodd Fiala      eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values,
2209666ba75STodd Fiala      "If true, LLDB will use the column information from the debug info to "
2219666ba75STodd Fiala      "mark the current position when displaying a stopped context."},
2229666ba75STodd Fiala     {"stop-show-column-ansi-prefix", OptionValue::eTypeFormatEntity, true, 0,
2239666ba75STodd Fiala      DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX, nullptr,
2249666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2259666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format at the "
2269666ba75STodd Fiala      "immediately before the column to be marked."},
2279666ba75STodd Fiala     {"stop-show-column-ansi-suffix", OptionValue::eTypeFormatEntity, true, 0,
2289666ba75STodd Fiala      DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX, nullptr,
2299666ba75STodd Fiala      "When displaying the column marker in a color-enabled (i.e. ANSI) "
2309666ba75STodd Fiala      "terminal, use the ANSI terminal code specified in this format "
2319666ba75STodd Fiala      "immediately after the column to be marked."},
232b9c1b51eSKate Stone     {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr,
233b9c1b51eSKate Stone      "The maximum number of columns to use for displaying text."},
234b9c1b51eSKate Stone     {"thread-format", OptionValue::eTypeFormatEntity, true, 0,
235b9c1b51eSKate Stone      DEFAULT_THREAD_FORMAT, nullptr, "The default thread format string to use "
236b9c1b51eSKate Stone                                      "when displaying thread information."},
2376a9767c7SJim Ingham     {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
2386a9767c7SJim Ingham      DEFAULT_THREAD_STOP_FORMAT, nullptr, "The default thread format  "
2396a9767c7SJim Ingham                                      "string to usewhen displaying thread "
2406a9767c7SJim Ingham                                      "information as part of the stop display."},
241b9c1b51eSKate Stone     {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr,
242b9c1b51eSKate Stone      nullptr, "Whether to use an external editor or not."},
243b9c1b51eSKate Stone     {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
244b9c1b51eSKate Stone      "Whether to use Ansi color codes or not."},
245b9c1b51eSKate Stone     {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
246b9c1b51eSKate Stone      nullptr, "If true, LLDB will automatically display small structs in "
247b9c1b51eSKate Stone               "one-liner format (default: true)."},
248b9c1b51eSKate Stone     {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
249b9c1b51eSKate Stone      "If true, LLDB will auto indent/outdent code. Currently only supported in "
250b9c1b51eSKate Stone      "the REPL (default: true)."},
251b9c1b51eSKate Stone     {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
252b9c1b51eSKate Stone      "If true, LLDB will print the values of variables declared in an "
253b9c1b51eSKate Stone      "expression. Currently only supported in the REPL (default: true)."},
254b9c1b51eSKate Stone     {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, nullptr,
255b9c1b51eSKate Stone      "The tab size to use when indenting code in multi-line input mode "
256b9c1b51eSKate Stone      "(default: 4)."},
257b9c1b51eSKate Stone     {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
258b9c1b51eSKate Stone      nullptr, "If true, LLDB will automatically escape non-printable and "
259b9c1b51eSKate Stone               "escape characters when formatting strings."},
260b9c1b51eSKate Stone     {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
26167cc0636SGreg Clayton 
262b9c1b51eSKate Stone enum {
26367cc0636SGreg Clayton   ePropertyAutoConfirm = 0,
264aff1b357SJason Molenda   ePropertyDisassemblyFormat,
26567cc0636SGreg Clayton   ePropertyFrameFormat,
26667cc0636SGreg Clayton   ePropertyNotiftVoid,
26767cc0636SGreg Clayton   ePropertyPrompt,
26867cc0636SGreg Clayton   ePropertyScriptLanguage,
26967cc0636SGreg Clayton   ePropertyStopDisassemblyCount,
27067cc0636SGreg Clayton   ePropertyStopDisassemblyDisplay,
27167cc0636SGreg Clayton   ePropertyStopLineCountAfter,
27267cc0636SGreg Clayton   ePropertyStopLineCountBefore,
2739666ba75STodd Fiala   ePropertyStopShowColumn,
2749666ba75STodd Fiala   ePropertyStopShowColumnAnsiPrefix,
2759666ba75STodd Fiala   ePropertyStopShowColumnAnsiSuffix,
27667cc0636SGreg Clayton   ePropertyTerminalWidth,
27767cc0636SGreg Clayton   ePropertyThreadFormat,
2786a9767c7SJim Ingham   ePropertyThreadStopFormat,
279c3ce7f27SMichael Sartain   ePropertyUseExternalEditor,
280c3ce7f27SMichael Sartain   ePropertyUseColor,
281ebdc1ac0SEnrico Granata   ePropertyAutoOneLineSummaries,
2826681041dSSean Callanan   ePropertyAutoIndent,
2836681041dSSean Callanan   ePropertyPrintDecls,
2846681041dSSean Callanan   ePropertyTabSize,
285ebdc1ac0SEnrico Granata   ePropertyEscapeNonPrintables
28667cc0636SGreg Clayton };
28767cc0636SGreg Clayton 
288df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr;
2894c05410fSGreg Clayton 
290b9c1b51eSKate Stone Error Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
2914c05410fSGreg Clayton                                  VarSetOperationType op,
29231d97a5cSZachary Turner   llvm::StringRef property_path, llvm::StringRef value) {
29331d97a5cSZachary Turner   bool is_load_script = (property_path == "target.load-script-from-symbol-file");
29431d97a5cSZachary Turner   bool is_escape_non_printables = (property_path == "escape-non-printables");
29584a53dfbSEnrico Granata   TargetSP target_sp;
296397ddd5fSEnrico Granata   LoadScriptFromSymFile load_script_old_value;
297b9c1b51eSKate Stone   if (is_load_script && exe_ctx->GetTargetSP()) {
29884a53dfbSEnrico Granata     target_sp = exe_ctx->GetTargetSP();
299b9c1b51eSKate Stone     load_script_old_value =
300b9c1b51eSKate Stone         target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
30184a53dfbSEnrico Granata   }
3024c05410fSGreg Clayton   Error error(Properties::SetPropertyValue(exe_ctx, op, property_path, value));
303b9c1b51eSKate Stone   if (error.Success()) {
30484a53dfbSEnrico Granata     // FIXME it would be nice to have "on-change" callbacks for properties
30531d97a5cSZachary Turner     if (property_path == g_properties[ePropertyPrompt].name) {
306514d8cd8SZachary Turner       llvm::StringRef new_prompt = GetPrompt();
307b9c1b51eSKate Stone       std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes(
308b9c1b51eSKate Stone           new_prompt, GetUseColor());
309c3ce7f27SMichael Sartain       if (str.length())
310771ef6d4SMalcolm Parsons         new_prompt = str;
31144d93782SGreg Clayton       GetCommandInterpreter().UpdatePrompt(new_prompt);
312*2f3df613SZachary Turner       auto bytes = llvm::make_unique<EventDataBytes>(new_prompt);
313*2f3df613SZachary Turner       auto prompt_change_event_sp = std::make_shared<Event>(
314*2f3df613SZachary Turner           CommandInterpreter::eBroadcastBitResetPrompt, bytes.release());
3154c05410fSGreg Clayton       GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp);
31631d97a5cSZachary Turner     } else if (property_path == g_properties[ePropertyUseColor].name) {
317b9c1b51eSKate Stone       // use-color changed. Ping the prompt so it can reset the ansi terminal
318b9c1b51eSKate Stone       // codes.
319c3ce7f27SMichael Sartain       SetPrompt(GetPrompt());
320b9c1b51eSKate Stone     } else if (is_load_script && target_sp &&
321b9c1b51eSKate Stone                load_script_old_value == eLoadScriptFromSymFileWarn) {
322b9c1b51eSKate Stone       if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() ==
323b9c1b51eSKate Stone           eLoadScriptFromSymFileTrue) {
32484a53dfbSEnrico Granata         std::list<Error> errors;
3259730339bSEnrico Granata         StreamString feedback_stream;
326b9c1b51eSKate Stone         if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) {
32744d93782SGreg Clayton           StreamFileSP stream_sp(GetErrorFile());
328b9c1b51eSKate Stone           if (stream_sp) {
329b9c1b51eSKate Stone             for (auto error : errors) {
33044d93782SGreg Clayton               stream_sp->Printf("%s\n", error.AsCString());
33184a53dfbSEnrico Granata             }
3329730339bSEnrico Granata             if (feedback_stream.GetSize())
333c156427dSZachary Turner               stream_sp->PutCString(feedback_stream.GetString());
33444d93782SGreg Clayton           }
33584a53dfbSEnrico Granata         }
33684a53dfbSEnrico Granata       }
337b9c1b51eSKate Stone     } else if (is_escape_non_printables) {
338ebdc1ac0SEnrico Granata       DataVisualization::ForceUpdate();
339ebdc1ac0SEnrico Granata     }
3404c05410fSGreg Clayton   }
3414c05410fSGreg Clayton   return error;
3424c05410fSGreg Clayton }
3434c05410fSGreg Clayton 
344b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const {
34567cc0636SGreg Clayton   const uint32_t idx = ePropertyAutoConfirm;
346b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
347b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
34867cc0636SGreg Clayton }
34967cc0636SGreg Clayton 
350b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const {
351aff1b357SJason Molenda   const uint32_t idx = ePropertyDisassemblyFormat;
352df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
353aff1b357SJason Molenda }
354aff1b357SJason Molenda 
355b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const {
35667cc0636SGreg Clayton   const uint32_t idx = ePropertyFrameFormat;
357df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
35867cc0636SGreg Clayton }
35967cc0636SGreg Clayton 
360b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const {
36167cc0636SGreg Clayton   const uint32_t idx = ePropertyNotiftVoid;
362b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
363b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
36467cc0636SGreg Clayton }
36567cc0636SGreg Clayton 
366514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const {
36767cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
368b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsString(
369b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_cstr_value);
37067cc0636SGreg Clayton }
37167cc0636SGreg Clayton 
372514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) {
37367cc0636SGreg Clayton   const uint32_t idx = ePropertyPrompt;
374df370550SEugene Zelenko   m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p);
375514d8cd8SZachary Turner   llvm::StringRef new_prompt = GetPrompt();
376b9c1b51eSKate Stone   std::string str =
377b9c1b51eSKate Stone       lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor());
378c3ce7f27SMichael Sartain   if (str.length())
379771ef6d4SMalcolm Parsons     new_prompt = str;
38044d93782SGreg Clayton   GetCommandInterpreter().UpdatePrompt(new_prompt);
38167cc0636SGreg Clayton }
38267cc0636SGreg Clayton 
383b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const {
38467cc0636SGreg Clayton   const uint32_t idx = ePropertyThreadFormat;
385df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
38667cc0636SGreg Clayton }
38767cc0636SGreg Clayton 
3886a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const {
3896a9767c7SJim Ingham   const uint32_t idx = ePropertyThreadStopFormat;
3906a9767c7SJim Ingham   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
3916a9767c7SJim Ingham }
3926a9767c7SJim Ingham 
393b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const {
39467cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
395b9c1b51eSKate Stone   return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(
396b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
39767cc0636SGreg Clayton }
39867cc0636SGreg Clayton 
399b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) {
40067cc0636SGreg Clayton   const uint32_t idx = ePropertyScriptLanguage;
401b9c1b51eSKate Stone   return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx,
402b9c1b51eSKate Stone                                                           script_lang);
40367cc0636SGreg Clayton }
40467cc0636SGreg Clayton 
405b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const {
40667cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
407b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
408b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
40967cc0636SGreg Clayton }
41067cc0636SGreg Clayton 
411b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) {
41267cc0636SGreg Clayton   const uint32_t idx = ePropertyTerminalWidth;
413df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width);
41467cc0636SGreg Clayton }
41567cc0636SGreg Clayton 
416b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const {
41767cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
418b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
419b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
42067cc0636SGreg Clayton }
42167cc0636SGreg Clayton 
422b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) {
42367cc0636SGreg Clayton   const uint32_t idx = ePropertyUseExternalEditor;
424df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
42567cc0636SGreg Clayton }
42667cc0636SGreg Clayton 
427b9c1b51eSKate Stone bool Debugger::GetUseColor() const {
428c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
429b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsBoolean(
430b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value != 0);
431c3ce7f27SMichael Sartain }
432c3ce7f27SMichael Sartain 
433b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) {
434c3ce7f27SMichael Sartain   const uint32_t idx = ePropertyUseColor;
435df370550SEugene Zelenko   bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
436c3ce7f27SMichael Sartain   SetPrompt(GetPrompt());
437c3ce7f27SMichael Sartain   return ret;
438c3ce7f27SMichael Sartain }
439c3ce7f27SMichael Sartain 
4409666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const {
4419666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumn;
4429666ba75STodd Fiala   return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
4439666ba75STodd Fiala       nullptr, idx, g_properties[idx].default_uint_value);
4449666ba75STodd Fiala }
4459666ba75STodd Fiala 
4469666ba75STodd Fiala const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiPrefix() const {
4479666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
4489666ba75STodd Fiala   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4499666ba75STodd Fiala }
4509666ba75STodd Fiala 
4519666ba75STodd Fiala const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiSuffix() const {
4529666ba75STodd Fiala   const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
4539666ba75STodd Fiala   return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
4549666ba75STodd Fiala }
4559666ba75STodd Fiala 
456b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const {
457b9c1b51eSKate Stone   const uint32_t idx =
458b9c1b51eSKate Stone       before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter;
459b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
460b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
46167cc0636SGreg Clayton }
46267cc0636SGreg Clayton 
463b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const {
46467cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyDisplay;
465b9c1b51eSKate Stone   return (Debugger::StopDisassemblyType)
466b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsEnumeration(
467b9c1b51eSKate Stone           nullptr, idx, g_properties[idx].default_uint_value);
46867cc0636SGreg Clayton }
46967cc0636SGreg Clayton 
470b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const {
47167cc0636SGreg Clayton   const uint32_t idx = ePropertyStopDisassemblyCount;
472b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsSInt64(
473b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
47467cc0636SGreg Clayton }
475e372b98dSGreg Clayton 
476b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const {
47790a8db30SEnrico Granata   const uint32_t idx = ePropertyAutoOneLineSummaries;
478df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
479ebdc1ac0SEnrico Granata }
480553fad5cSEnrico Granata 
481b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const {
482ebdc1ac0SEnrico Granata   const uint32_t idx = ePropertyEscapeNonPrintables;
483df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
484553fad5cSEnrico Granata }
485553fad5cSEnrico Granata 
486b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const {
4876681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
488df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
4896681041dSSean Callanan }
4906681041dSSean Callanan 
491b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) {
4926681041dSSean Callanan   const uint32_t idx = ePropertyAutoIndent;
493df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
4946681041dSSean Callanan }
4956681041dSSean Callanan 
496b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const {
4976681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
498df370550SEugene Zelenko   return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true);
4996681041dSSean Callanan }
5006681041dSSean Callanan 
501b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) {
5026681041dSSean Callanan   const uint32_t idx = ePropertyPrintDecls;
503df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
5046681041dSSean Callanan }
5056681041dSSean Callanan 
506b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const {
5076681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
508b9c1b51eSKate Stone   return m_collection_sp->GetPropertyAtIndexAsUInt64(
509b9c1b51eSKate Stone       nullptr, idx, g_properties[idx].default_uint_value);
5106681041dSSean Callanan }
5116681041dSSean Callanan 
512b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) {
5136681041dSSean Callanan   const uint32_t idx = ePropertyTabSize;
514df370550SEugene Zelenko   return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size);
5156681041dSSean Callanan }
5166681041dSSean Callanan 
5171b654882SGreg Clayton #pragma mark Debugger
5181b654882SGreg Clayton 
51967cc0636SGreg Clayton // const DebuggerPropertiesSP &
52067cc0636SGreg Clayton // Debugger::GetSettings() const
52167cc0636SGreg Clayton //{
52267cc0636SGreg Clayton //    return m_properties_sp;
52367cc0636SGreg Clayton //}
52467cc0636SGreg Clayton //
52599d0faf2SGreg Clayton 
526b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
527b9c1b51eSKate Stone   assert(g_debugger_list_ptr == nullptr &&
528b9c1b51eSKate Stone          "Debugger::Initialize called more than once!");
5296c42e063SGreg Clayton   g_debugger_list_mutex_ptr = new std::recursive_mutex();
5306c42e063SGreg Clayton   g_debugger_list_ptr = new DebuggerList();
5315fb8f797SGreg Clayton   g_load_plugin_callback = load_plugin_callback;
53299d0faf2SGreg Clayton }
53330fdc8d8SChris Lattner 
534b9c1b51eSKate Stone void Debugger::Terminate() {
535b9c1b51eSKate Stone   assert(g_debugger_list_ptr &&
536b9c1b51eSKate Stone          "Debugger::Terminate called without a matching Debugger::Initialize!");
537e6e2bb38SZachary Turner 
538b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
53999d0faf2SGreg Clayton     // Clear our master list of debugger objects
5406c42e063SGreg Clayton     {
5416c42e063SGreg Clayton       std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
5426c42e063SGreg Clayton       for (const auto &debugger : *g_debugger_list_ptr)
543f3cd1819SOleksiy Vyalov         debugger->Clear();
5446c42e063SGreg Clayton       g_debugger_list_ptr->clear();
5456c42e063SGreg Clayton     }
5466c42e063SGreg Clayton   }
54730fdc8d8SChris Lattner }
54830fdc8d8SChris Lattner 
549b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); }
55020bd37f7SCaroline Tice 
551b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); }
55220bd37f7SCaroline Tice 
553b9c1b51eSKate Stone bool Debugger::LoadPlugin(const FileSpec &spec, Error &error) {
554b9c1b51eSKate Stone   if (g_load_plugin_callback) {
555b9c1b51eSKate Stone     llvm::sys::DynamicLibrary dynlib =
556b9c1b51eSKate Stone         g_load_plugin_callback(shared_from_this(), spec, error);
557b9c1b51eSKate Stone     if (dynlib.isValid()) {
55858a559c0SZachary Turner       m_loaded_plugins.push_back(dynlib);
55921dfcd9dSEnrico Granata       return true;
56021dfcd9dSEnrico Granata     }
561b9c1b51eSKate Stone   } else {
5625fb8f797SGreg Clayton     // The g_load_plugin_callback is registered in SBDebugger::Initialize()
5635fb8f797SGreg Clayton     // and if the public API layer isn't available (code is linking against
5645fb8f797SGreg Clayton     // all of the internal LLDB static libraries), then we can't load plugins
5655fb8f797SGreg Clayton     error.SetErrorString("Public API layer is not available");
5665fb8f797SGreg Clayton   }
56721dfcd9dSEnrico Granata   return false;
56821dfcd9dSEnrico Granata }
56921dfcd9dSEnrico Granata 
57021dfcd9dSEnrico Granata static FileSpec::EnumerateDirectoryResult
5717d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
572b9c1b51eSKate Stone                    const FileSpec &file_spec) {
57321dfcd9dSEnrico Granata   Error error;
57421dfcd9dSEnrico Granata 
57521dfcd9dSEnrico Granata   static ConstString g_dylibext("dylib");
5763cf443ddSMichael Sartain   static ConstString g_solibext("so");
57721dfcd9dSEnrico Granata 
57821dfcd9dSEnrico Granata   if (!baton)
57921dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultQuit;
58021dfcd9dSEnrico Granata 
58121dfcd9dSEnrico Granata   Debugger *debugger = (Debugger *)baton;
58221dfcd9dSEnrico Granata 
5837d86ee5aSZachary Turner   namespace fs = llvm::sys::fs;
58421dfcd9dSEnrico Granata   // If we have a regular file, a symbolic link or unknown file type, try
58521dfcd9dSEnrico Granata   // and process the file. We must handle unknown as sometimes the directory
58621dfcd9dSEnrico Granata   // enumeration might be enumerating a file system that doesn't have correct
58721dfcd9dSEnrico Granata   // file type information.
5887d86ee5aSZachary Turner   if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
5897d86ee5aSZachary Turner       ft == fs::file_type::type_unknown) {
59021dfcd9dSEnrico Granata     FileSpec plugin_file_spec(file_spec);
59121dfcd9dSEnrico Granata     plugin_file_spec.ResolvePath();
59221dfcd9dSEnrico Granata 
5933cf443ddSMichael Sartain     if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
594b9c1b51eSKate Stone         plugin_file_spec.GetFileNameExtension() != g_solibext) {
59521dfcd9dSEnrico Granata       return FileSpec::eEnumerateDirectoryResultNext;
5963cf443ddSMichael Sartain     }
59721dfcd9dSEnrico Granata 
598e743c782SEnrico Granata     Error plugin_load_error;
599e743c782SEnrico Granata     debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
60021dfcd9dSEnrico Granata 
60121dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultNext;
6027d86ee5aSZachary Turner   } else if (ft == fs::file_type::directory_file ||
6037d86ee5aSZachary Turner              ft == fs::file_type::symlink_file ||
6047d86ee5aSZachary Turner              ft == fs::file_type::type_unknown) {
60521dfcd9dSEnrico Granata     // Try and recurse into anything that a directory or symbolic link.
60621dfcd9dSEnrico Granata     // We must also do this for unknown as sometimes the directory enumeration
6076a7f3338SBruce Mitchener     // might be enumerating a file system that doesn't have correct file type
60821dfcd9dSEnrico Granata     // information.
60921dfcd9dSEnrico Granata     return FileSpec::eEnumerateDirectoryResultEnter;
61021dfcd9dSEnrico Granata   }
61121dfcd9dSEnrico Granata 
61221dfcd9dSEnrico Granata   return FileSpec::eEnumerateDirectoryResultNext;
61321dfcd9dSEnrico Granata }
61421dfcd9dSEnrico Granata 
615b9c1b51eSKate Stone void Debugger::InstanceInitialize() {
61621dfcd9dSEnrico Granata   FileSpec dir_spec;
61721dfcd9dSEnrico Granata   const bool find_directories = true;
61821dfcd9dSEnrico Granata   const bool find_files = true;
61921dfcd9dSEnrico Granata   const bool find_other = true;
62021dfcd9dSEnrico Granata   char dir_path[PATH_MAX];
621b9c1b51eSKate Stone   if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) {
622b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
623b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
624b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
62521dfcd9dSEnrico Granata     }
62621dfcd9dSEnrico Granata   }
62721dfcd9dSEnrico Granata 
628b9c1b51eSKate Stone   if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) {
629b9c1b51eSKate Stone     if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
630b9c1b51eSKate Stone       FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
631b9c1b51eSKate Stone                                    find_other, LoadPluginCallback, this);
63221dfcd9dSEnrico Granata     }
63321dfcd9dSEnrico Granata   }
634e8cd0c98SGreg Clayton 
635e8cd0c98SGreg Clayton   PluginManager::DebuggerInitialize(*this);
63621dfcd9dSEnrico Granata }
63721dfcd9dSEnrico Granata 
638b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback,
639b9c1b51eSKate Stone                                     void *baton) {
640228063cdSJim Ingham   DebuggerSP debugger_sp(new Debugger(log_callback, baton));
641b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6426c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6436c42e063SGreg Clayton     g_debugger_list_ptr->push_back(debugger_sp);
6446611103cSGreg Clayton   }
64521dfcd9dSEnrico Granata   debugger_sp->InstanceInitialize();
6466611103cSGreg Clayton   return debugger_sp;
6476611103cSGreg Clayton }
6486611103cSGreg Clayton 
649b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) {
650df370550SEugene Zelenko   if (!debugger_sp)
651e02657b1SCaroline Tice     return;
652e02657b1SCaroline Tice 
6538314c525SJim Ingham   debugger_sp->Clear();
6548314c525SJim Ingham 
655b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6566c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6576c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
658b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
659b9c1b51eSKate Stone       if ((*pos).get() == debugger_sp.get()) {
6606c42e063SGreg Clayton         g_debugger_list_ptr->erase(pos);
661e02657b1SCaroline Tice         return;
662e02657b1SCaroline Tice       }
663e02657b1SCaroline Tice     }
664e02657b1SCaroline Tice   }
665c15f55e2SGreg Clayton }
666e02657b1SCaroline Tice 
6674d122c40SGreg Clayton DebuggerSP
668b9c1b51eSKate Stone Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) {
6694d122c40SGreg Clayton   DebuggerSP debugger_sp;
670b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6716c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6726c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
673b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
674b9c1b51eSKate Stone       if ((*pos)->m_instance_name == instance_name) {
6756920b52bSGreg Clayton         debugger_sp = *pos;
6766920b52bSGreg Clayton         break;
6776920b52bSGreg Clayton       }
6786920b52bSGreg Clayton     }
6796920b52bSGreg Clayton   }
6803df9a8dfSCaroline Tice   return debugger_sp;
6813df9a8dfSCaroline Tice }
6826611103cSGreg Clayton 
683b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) {
6844d122c40SGreg Clayton   TargetSP target_sp;
685b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
6866c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
6876c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
688b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
6896611103cSGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid);
6906611103cSGreg Clayton       if (target_sp)
6916611103cSGreg Clayton         break;
6926611103cSGreg Clayton     }
693c15f55e2SGreg Clayton   }
6946611103cSGreg Clayton   return target_sp;
6956611103cSGreg Clayton }
6966611103cSGreg Clayton 
697b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) {
698e4e45924SGreg Clayton   TargetSP target_sp;
699b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
7006c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
7016c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
702b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
703e4e45924SGreg Clayton       target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process);
704e4e45924SGreg Clayton       if (target_sp)
705e4e45924SGreg Clayton         break;
706e4e45924SGreg Clayton     }
707c15f55e2SGreg Clayton   }
708e4e45924SGreg Clayton   return target_sp;
709e4e45924SGreg Clayton }
710e4e45924SGreg Clayton 
711b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
712b9c1b51eSKate Stone     : UserID(g_unique_id++),
713*2f3df613SZachary Turner       Properties(std::make_shared<OptionValueProperties>()),
714*2f3df613SZachary Turner       m_input_file_sp(std::make_shared<StreamFile>(stdin, false)),
715*2f3df613SZachary Turner       m_output_file_sp(std::make_shared<StreamFile>(stdout, false)),
716*2f3df613SZachary Turner       m_error_file_sp(std::make_shared<StreamFile>(stderr, false)),
717583bbb1dSJim Ingham       m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()),
718b9c1b51eSKate Stone       m_terminal_state(), m_target_list(*this), m_platform_list(),
719583bbb1dSJim Ingham       m_listener_sp(Listener::MakeListener("lldb.Debugger")),
720b9c1b51eSKate Stone       m_source_manager_ap(), m_source_file_cache(),
721*2f3df613SZachary Turner       m_command_interpreter_ap(llvm::make_unique<CommandInterpreter>(
722*2f3df613SZachary Turner           *this, eScriptLanguageDefault, false)),
723b9c1b51eSKate Stone       m_input_reader_stack(), m_instance_name(), m_loaded_plugins(),
724b9c1b51eSKate Stone       m_event_handler_thread(), m_io_handler_thread(),
7254329fe42SGreg Clayton       m_sync_broadcaster(nullptr, "lldb.debugger.sync"),
726b9c1b51eSKate Stone       m_forward_listener_sp(), m_clear_once() {
72767cc0636SGreg Clayton   char instance_cstr[256];
72867cc0636SGreg Clayton   snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID());
72967cc0636SGreg Clayton   m_instance_name.SetCString(instance_cstr);
730228063cdSJim Ingham   if (log_callback)
731*2f3df613SZachary Turner     m_log_callback_stream_sp =
732*2f3df613SZachary Turner         std::make_shared<StreamCallback>(log_callback, baton);
7336611103cSGreg Clayton   m_command_interpreter_ap->Initialize();
734ded470d3SGreg Clayton   // Always add our default platform to the platform list
735615eb7e6SGreg Clayton   PlatformSP default_platform_sp(Platform::GetHostPlatform());
736df370550SEugene Zelenko   assert(default_platform_sp);
737ded470d3SGreg Clayton   m_platform_list.Append(default_platform_sp, true);
73867cc0636SGreg Clayton 
739754a9369SGreg Clayton   m_collection_sp->Initialize(g_properties);
740b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
741b9c1b51eSKate Stone       ConstString("target"),
742b9c1b51eSKate Stone       ConstString("Settings specify to debugging targets."), true,
74367cc0636SGreg Clayton       Target::GetGlobalProperties()->GetValueProperties());
744b9c1b51eSKate Stone   m_collection_sp->AppendProperty(
745b9c1b51eSKate Stone       ConstString("platform"), ConstString("Platform settings."), true,
74663acdfdeSOleksiy Vyalov       Platform::GetGlobalPlatformProperties()->GetValueProperties());
747b9c1b51eSKate Stone   if (m_command_interpreter_ap) {
748b9c1b51eSKate Stone     m_collection_sp->AppendProperty(
749b9c1b51eSKate Stone         ConstString("interpreter"),
750754a9369SGreg Clayton         ConstString("Settings specify to the debugger's command interpreter."),
751b9c1b51eSKate Stone         true, m_command_interpreter_ap->GetValueProperties());
752754a9369SGreg Clayton   }
753b9c1b51eSKate Stone   OptionValueSInt64 *term_width =
754b9c1b51eSKate Stone       m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(
755b9c1b51eSKate Stone           nullptr, ePropertyTerminalWidth);
75667cc0636SGreg Clayton   term_width->SetMinimumValue(10);
75767cc0636SGreg Clayton   term_width->SetMaximumValue(1024);
758c3ce7f27SMichael Sartain 
759c3ce7f27SMichael Sartain   // Turn off use-color if this is a dumb terminal.
760c3ce7f27SMichael Sartain   const char *term = getenv("TERM");
761c3ce7f27SMichael Sartain   if (term && !strcmp(term, "dumb"))
762c3ce7f27SMichael Sartain     SetUseColor(false);
76330fdc8d8SChris Lattner }
76430fdc8d8SChris Lattner 
765b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); }
7668314c525SJim Ingham 
767b9c1b51eSKate Stone void Debugger::Clear() {
7684329fe42SGreg Clayton   //----------------------------------------------------------------------
7694329fe42SGreg Clayton   // Make sure we call this function only once. With the C++ global
7704329fe42SGreg Clayton   // destructor chain having a list of debuggers and with code that can be
7714329fe42SGreg Clayton   // running on other threads, we need to ensure this doesn't happen
7724329fe42SGreg Clayton   // multiple times.
7734329fe42SGreg Clayton   //
7744329fe42SGreg Clayton   // The following functions call Debugger::Clear():
7754329fe42SGreg Clayton   //     Debugger::~Debugger();
7764329fe42SGreg Clayton   //     static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp);
7774329fe42SGreg Clayton   //     static void Debugger::Terminate();
7784329fe42SGreg Clayton   //----------------------------------------------------------------------
779c5f28e2aSKamil Rytarowski   llvm::call_once(m_clear_once, [this]() {
78044d93782SGreg Clayton     ClearIOHandlers();
78144d93782SGreg Clayton     StopIOHandlerThread();
78244d93782SGreg Clayton     StopEventHandlerThread();
783583bbb1dSJim Ingham     m_listener_sp->Clear();
7846611103cSGreg Clayton     int num_targets = m_target_list.GetNumTargets();
785b9c1b51eSKate Stone     for (int i = 0; i < num_targets; i++) {
786ccbc08e6SGreg Clayton       TargetSP target_sp(m_target_list.GetTargetAtIndex(i));
787b9c1b51eSKate Stone       if (target_sp) {
788ccbc08e6SGreg Clayton         ProcessSP process_sp(target_sp->GetProcessSP());
7896611103cSGreg Clayton         if (process_sp)
7901fd07059SJim Ingham           process_sp->Finalize();
791ccbc08e6SGreg Clayton         target_sp->Destroy();
7926611103cSGreg Clayton       }
79330fdc8d8SChris Lattner     }
794583bbb1dSJim Ingham     m_broadcaster_manager_sp->Clear();
79530fdc8d8SChris Lattner 
796b9c1b51eSKate Stone     // Close the input file _before_ we close the input read communications
797b9c1b51eSKate Stone     // class
7980d69a3a4SGreg Clayton     // as it does NOT own the input file, our m_input_file does.
799c5917d9aSJim Ingham     m_terminal_state.Clear();
80044d93782SGreg Clayton     if (m_input_file_sp)
80144d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
8020c4129f2SGreg Clayton 
8030c4129f2SGreg Clayton     m_command_interpreter_ap->Clear();
8044329fe42SGreg Clayton   });
8058314c525SJim Ingham }
80630fdc8d8SChris Lattner 
807b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const {
80844d93782SGreg Clayton   //    return m_input_comm.GetCloseOnEOF();
80944d93782SGreg Clayton   return false;
810fc3f027dSGreg Clayton }
811fc3f027dSGreg Clayton 
812b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) {
81344d93782SGreg Clayton   //    m_input_comm.SetCloseOnEOF(b);
814fc3f027dSGreg Clayton }
815fc3f027dSGreg Clayton 
816b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() {
8176611103cSGreg Clayton   return !m_command_interpreter_ap->GetSynchronous();
81830fdc8d8SChris Lattner }
81930fdc8d8SChris Lattner 
820b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) {
8216611103cSGreg Clayton   m_command_interpreter_ap->SetSynchronous(!async_execution);
82230fdc8d8SChris Lattner }
82330fdc8d8SChris Lattner 
824b9c1b51eSKate Stone void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) {
82544d93782SGreg Clayton   if (m_input_file_sp)
82644d93782SGreg Clayton     m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership);
82744d93782SGreg Clayton   else
828*2f3df613SZachary Turner     m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
82944d93782SGreg Clayton 
83044d93782SGreg Clayton   File &in_file = m_input_file_sp->GetFile();
831df370550SEugene Zelenko   if (!in_file.IsValid())
83251b1e2d2SGreg Clayton     in_file.SetStream(stdin, true);
83330fdc8d8SChris Lattner 
834b9c1b51eSKate Stone   // Save away the terminal state if that is relevant, so that we can restore it
835b9c1b51eSKate Stone   // in RestoreInputState.
836c5917d9aSJim Ingham   SaveInputTerminalState();
83730fdc8d8SChris Lattner }
83830fdc8d8SChris Lattner 
839b9c1b51eSKate Stone void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) {
84044d93782SGreg Clayton   if (m_output_file_sp)
84144d93782SGreg Clayton     m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership);
84244d93782SGreg Clayton   else
843*2f3df613SZachary Turner     m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
84444d93782SGreg Clayton 
84544d93782SGreg Clayton   File &out_file = m_output_file_sp->GetFile();
846df370550SEugene Zelenko   if (!out_file.IsValid())
84751b1e2d2SGreg Clayton     out_file.SetStream(stdout, false);
8482f88aadfSCaroline Tice 
849b588726eSEnrico Granata   // do not create the ScriptInterpreter just for setting the output file handle
850b588726eSEnrico Granata   // as the constructor will know how to do the right thing on its own
851b588726eSEnrico Granata   const bool can_create = false;
852b9c1b51eSKate Stone   ScriptInterpreter *script_interpreter =
853b9c1b51eSKate Stone       GetCommandInterpreter().GetScriptInterpreter(can_create);
854b588726eSEnrico Granata   if (script_interpreter)
855b588726eSEnrico Granata     script_interpreter->ResetOutputFileHandle(fh);
85630fdc8d8SChris Lattner }
85730fdc8d8SChris Lattner 
858b9c1b51eSKate Stone void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) {
85944d93782SGreg Clayton   if (m_error_file_sp)
86044d93782SGreg Clayton     m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership);
86144d93782SGreg Clayton   else
862*2f3df613SZachary Turner     m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership);
86344d93782SGreg Clayton 
86444d93782SGreg Clayton   File &err_file = m_error_file_sp->GetFile();
865df370550SEugene Zelenko   if (!err_file.IsValid())
86651b1e2d2SGreg Clayton     err_file.SetStream(stderr, false);
86730fdc8d8SChris Lattner }
86830fdc8d8SChris Lattner 
869b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() {
870b9c1b51eSKate Stone   if (m_input_file_sp) {
87144d93782SGreg Clayton     File &in_file = m_input_file_sp->GetFile();
872c5917d9aSJim Ingham     if (in_file.GetDescriptor() != File::kInvalidDescriptor)
873c5917d9aSJim Ingham       m_terminal_state.Save(in_file.GetDescriptor(), true);
874c5917d9aSJim Ingham   }
87544d93782SGreg Clayton }
876c5917d9aSJim Ingham 
877b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); }
878c5917d9aSJim Ingham 
879b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() {
88030fdc8d8SChris Lattner   ExecutionContext exe_ctx;
881c14ee32dSGreg Clayton   TargetSP target_sp(GetSelectedTarget());
882c14ee32dSGreg Clayton   exe_ctx.SetTargetSP(target_sp);
88330fdc8d8SChris Lattner 
884b9c1b51eSKate Stone   if (target_sp) {
885c14ee32dSGreg Clayton     ProcessSP process_sp(target_sp->GetProcessSP());
886c14ee32dSGreg Clayton     exe_ctx.SetProcessSP(process_sp);
887b9c1b51eSKate Stone     if (process_sp && !process_sp->IsRunning()) {
888c14ee32dSGreg Clayton       ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread());
889b9c1b51eSKate Stone       if (thread_sp) {
890c14ee32dSGreg Clayton         exe_ctx.SetThreadSP(thread_sp);
891c14ee32dSGreg Clayton         exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame());
892df370550SEugene Zelenko         if (exe_ctx.GetFramePtr() == nullptr)
893c14ee32dSGreg Clayton           exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0));
89430fdc8d8SChris Lattner       }
89530fdc8d8SChris Lattner     }
89630fdc8d8SChris Lattner   }
89730fdc8d8SChris Lattner   return exe_ctx;
89830fdc8d8SChris Lattner }
89930fdc8d8SChris Lattner 
900b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() {
90116ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
90244d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
903efed6131SCaroline Tice   if (reader_sp)
90444d93782SGreg Clayton     reader_sp->Interrupt();
905efed6131SCaroline Tice }
906efed6131SCaroline Tice 
907b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() {
90816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
90944d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
910efed6131SCaroline Tice   if (reader_sp)
91144d93782SGreg Clayton     reader_sp->GotEOF();
912efed6131SCaroline Tice }
913efed6131SCaroline Tice 
914b9c1b51eSKate Stone void Debugger::ClearIOHandlers() {
915b9c1b51eSKate Stone   // The bottom input reader should be the main debugger input reader.  We do
916b9c1b51eSKate Stone   // not want to close that one here.
91716ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
918b9c1b51eSKate Stone   while (m_input_reader_stack.GetSize() > 1) {
91944d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
9203d6086f6SCaroline Tice     if (reader_sp)
9214446487dSPavel Labath       PopIOHandler(reader_sp);
9223d6086f6SCaroline Tice   }
9233d6086f6SCaroline Tice }
9243d6086f6SCaroline Tice 
925b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() {
926b9c1b51eSKate Stone   while (true) {
92744d93782SGreg Clayton     IOHandlerSP reader_sp(m_input_reader_stack.Top());
92830fdc8d8SChris Lattner     if (!reader_sp)
92930fdc8d8SChris Lattner       break;
93030fdc8d8SChris Lattner 
93144d93782SGreg Clayton     reader_sp->Run();
93244d93782SGreg Clayton 
93344d93782SGreg Clayton     // Remove all input readers that are done from the top of the stack
934b9c1b51eSKate Stone     while (true) {
93544d93782SGreg Clayton       IOHandlerSP top_reader_sp = m_input_reader_stack.Top();
93644d93782SGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9374446487dSPavel Labath         PopIOHandler(top_reader_sp);
93830fdc8d8SChris Lattner       else
93930fdc8d8SChris Lattner         break;
94030fdc8d8SChris Lattner     }
94130fdc8d8SChris Lattner   }
94244d93782SGreg Clayton   ClearIOHandlers();
94344d93782SGreg Clayton }
94430fdc8d8SChris Lattner 
945b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) {
94644d93782SGreg Clayton   return m_input_reader_stack.IsTop(reader_sp);
94744d93782SGreg Clayton }
94830fdc8d8SChris Lattner 
949b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type,
950b9c1b51eSKate Stone                                       IOHandler::Type second_top_type) {
9516681041dSSean Callanan   return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type);
9526681041dSSean Callanan }
9536681041dSSean Callanan 
954b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) {
9554446487dSPavel Labath   lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile();
9564446487dSPavel Labath   m_input_reader_stack.PrintAsync(stream.get(), s, len);
9574446487dSPavel Labath }
95844d93782SGreg Clayton 
959b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) {
96044d93782SGreg Clayton   return m_input_reader_stack.GetTopIOHandlerControlSequence(ch);
96130fdc8d8SChris Lattner }
96230fdc8d8SChris Lattner 
963b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() {
964a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerCommandPrefix();
965a487aa4cSKate Stone }
966a487aa4cSKate Stone 
967b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() {
968a487aa4cSKate Stone   return m_input_reader_stack.GetTopIOHandlerHelpPrologue();
969a487aa4cSKate Stone }
970a487aa4cSKate Stone 
971b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) {
97244d93782SGreg Clayton   PushIOHandler(reader_sp);
973577508dfSGreg Clayton 
974577508dfSGreg Clayton   IOHandlerSP top_reader_sp = reader_sp;
975b9c1b51eSKate Stone   while (top_reader_sp) {
976577508dfSGreg Clayton     top_reader_sp->Run();
977577508dfSGreg Clayton 
978b9c1b51eSKate Stone     if (top_reader_sp.get() == reader_sp.get()) {
979577508dfSGreg Clayton       if (PopIOHandler(reader_sp))
980577508dfSGreg Clayton         break;
981577508dfSGreg Clayton     }
982577508dfSGreg Clayton 
983b9c1b51eSKate Stone     while (true) {
984577508dfSGreg Clayton       top_reader_sp = m_input_reader_stack.Top();
985577508dfSGreg Clayton       if (top_reader_sp && top_reader_sp->GetIsDone())
9864446487dSPavel Labath         PopIOHandler(top_reader_sp);
987577508dfSGreg Clayton       else
988577508dfSGreg Clayton         break;
989577508dfSGreg Clayton     }
990577508dfSGreg Clayton   }
99144d93782SGreg Clayton }
99244d93782SGreg Clayton 
993b9c1b51eSKate Stone void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
994b9c1b51eSKate Stone                                                StreamFileSP &out,
995b9c1b51eSKate Stone                                                StreamFileSP &err) {
99644d93782SGreg Clayton   // Before an IOHandler runs, it must have in/out/err streams.
99744d93782SGreg Clayton   // This function is called when one ore more of the streams
998df370550SEugene Zelenko   // are nullptr. We use the top input reader's in/out/err streams,
99944d93782SGreg Clayton   // or fall back to the debugger file handles, or we fall back
100044d93782SGreg Clayton   // onto stdin/stdout/stderr as a last resort.
100144d93782SGreg Clayton 
100216ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
100344d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
100444d93782SGreg Clayton   // If no STDIN has been set, then set it appropriately
1005b9c1b51eSKate Stone   if (!in) {
100644d93782SGreg Clayton     if (top_reader_sp)
100744d93782SGreg Clayton       in = top_reader_sp->GetInputStreamFile();
100844d93782SGreg Clayton     else
100944d93782SGreg Clayton       in = GetInputFile();
101044d93782SGreg Clayton 
101144d93782SGreg Clayton     // If there is nothing, use stdin
101244d93782SGreg Clayton     if (!in)
1013*2f3df613SZachary Turner       in = std::make_shared<StreamFile>(stdin, false);
101444d93782SGreg Clayton   }
101544d93782SGreg Clayton   // If no STDOUT has been set, then set it appropriately
1016b9c1b51eSKate Stone   if (!out) {
101744d93782SGreg Clayton     if (top_reader_sp)
101844d93782SGreg Clayton       out = top_reader_sp->GetOutputStreamFile();
101944d93782SGreg Clayton     else
102044d93782SGreg Clayton       out = GetOutputFile();
102144d93782SGreg Clayton 
102244d93782SGreg Clayton     // If there is nothing, use stdout
102344d93782SGreg Clayton     if (!out)
1024*2f3df613SZachary Turner       out = std::make_shared<StreamFile>(stdout, false);
102544d93782SGreg Clayton   }
102644d93782SGreg Clayton   // If no STDERR has been set, then set it appropriately
1027b9c1b51eSKate Stone   if (!err) {
102844d93782SGreg Clayton     if (top_reader_sp)
102944d93782SGreg Clayton       err = top_reader_sp->GetErrorStreamFile();
103044d93782SGreg Clayton     else
103144d93782SGreg Clayton       err = GetErrorFile();
103244d93782SGreg Clayton 
103344d93782SGreg Clayton     // If there is nothing, use stderr
103444d93782SGreg Clayton     if (!err)
1035*2f3df613SZachary Turner       err = std::make_shared<StreamFile>(stdout, false);
103644d93782SGreg Clayton   }
103744d93782SGreg Clayton }
103844d93782SGreg Clayton 
1039b9c1b51eSKate Stone void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
104030fdc8d8SChris Lattner   if (!reader_sp)
104130fdc8d8SChris Lattner     return;
1042b44880caSCaroline Tice 
104316ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
10444446487dSPavel Labath 
10454446487dSPavel Labath   // Get the current top input reader...
104644d93782SGreg Clayton   IOHandlerSP top_reader_sp(m_input_reader_stack.Top());
1047b44880caSCaroline Tice 
1048b4874f1aSGreg Clayton   // Don't push the same IO handler twice...
10494446487dSPavel Labath   if (reader_sp == top_reader_sp)
10504446487dSPavel Labath     return;
10514446487dSPavel Labath 
105244d93782SGreg Clayton   // Push our new input reader
1053d5a0a01bSCaroline Tice   m_input_reader_stack.Push(reader_sp);
10544446487dSPavel Labath   reader_sp->Activate();
105544d93782SGreg Clayton 
105644d93782SGreg Clayton   // Interrupt the top input reader to it will exit its Run() function
105744d93782SGreg Clayton   // and let this new input reader take over
1058b9c1b51eSKate Stone   if (top_reader_sp) {
105944d93782SGreg Clayton     top_reader_sp->Deactivate();
10604446487dSPavel Labath     top_reader_sp->Cancel();
106130fdc8d8SChris Lattner   }
1062b4874f1aSGreg Clayton }
106330fdc8d8SChris Lattner 
1064b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) {
10654446487dSPavel Labath   if (!pop_reader_sp)
10664446487dSPavel Labath     return false;
106730fdc8d8SChris Lattner 
106816ff8604SSaleem Abdulrasool   std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex());
106944d93782SGreg Clayton 
107030fdc8d8SChris Lattner   // The reader on the stop of the stack is done, so let the next
10716a7f3338SBruce Mitchener   // read on the stack refresh its prompt and if there is one...
10724446487dSPavel Labath   if (m_input_reader_stack.IsEmpty())
10734446487dSPavel Labath     return false;
10744446487dSPavel Labath 
107544d93782SGreg Clayton   IOHandlerSP reader_sp(m_input_reader_stack.Top());
107630fdc8d8SChris Lattner 
10774446487dSPavel Labath   if (pop_reader_sp != reader_sp)
10784446487dSPavel Labath     return false;
10794446487dSPavel Labath 
108044d93782SGreg Clayton   reader_sp->Deactivate();
1081b4874f1aSGreg Clayton   reader_sp->Cancel();
1082d5a0a01bSCaroline Tice   m_input_reader_stack.Pop();
108330fdc8d8SChris Lattner 
1084d5a0a01bSCaroline Tice   reader_sp = m_input_reader_stack.Top();
108530fdc8d8SChris Lattner   if (reader_sp)
108644d93782SGreg Clayton     reader_sp->Activate();
108744d93782SGreg Clayton 
108844d93782SGreg Clayton   return true;
108930fdc8d8SChris Lattner }
10906611103cSGreg Clayton 
1091b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() {
1092*2f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, true);
10935b52f0c7SJim Ingham }
10945b52f0c7SJim Ingham 
1095b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() {
1096*2f3df613SZachary Turner   return std::make_shared<StreamAsynchronousIO>(*this, false);
10975b52f0c7SJim Ingham }
10985b52f0c7SJim Ingham 
1099b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() {
1100b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11016c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11026c42e063SGreg Clayton     return g_debugger_list_ptr->size();
1103061858ceSEnrico Granata   }
1104c15f55e2SGreg Clayton   return 0;
1105c15f55e2SGreg Clayton }
1106061858ceSEnrico Granata 
1107b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) {
1108061858ceSEnrico Granata   DebuggerSP debugger_sp;
1109061858ceSEnrico Granata 
1110b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11116c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11126c42e063SGreg Clayton     if (index < g_debugger_list_ptr->size())
11136c42e063SGreg Clayton       debugger_sp = g_debugger_list_ptr->at(index);
1114c15f55e2SGreg Clayton   }
1115061858ceSEnrico Granata 
1116061858ceSEnrico Granata   return debugger_sp;
1117061858ceSEnrico Granata }
1118061858ceSEnrico Granata 
1119b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) {
11204d122c40SGreg Clayton   DebuggerSP debugger_sp;
1121ebc1bb27SCaroline Tice 
1122b9c1b51eSKate Stone   if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
11236c42e063SGreg Clayton     std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
11246c42e063SGreg Clayton     DebuggerList::iterator pos, end = g_debugger_list_ptr->end();
1125b9c1b51eSKate Stone     for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) {
1126b9c1b51eSKate Stone       if ((*pos)->GetID() == id) {
1127ebc1bb27SCaroline Tice         debugger_sp = *pos;
1128ebc1bb27SCaroline Tice         break;
1129ebc1bb27SCaroline Tice       }
1130ebc1bb27SCaroline Tice     }
1131c15f55e2SGreg Clayton   }
1132ebc1bb27SCaroline Tice   return debugger_sp;
1133ebc1bb27SCaroline Tice }
11343df9a8dfSCaroline Tice 
11352643b905SSaleem Abdulrasool #if 0
11361b654882SGreg Clayton static void
1137b57e4a1bSJason Molenda TestPromptFormats (StackFrame *frame)
11381b654882SGreg Clayton {
1139df370550SEugene Zelenko     if (frame == nullptr)
11401b654882SGreg Clayton         return;
11411b654882SGreg Clayton 
11421b654882SGreg Clayton     StreamString s;
11431b654882SGreg Clayton     const char *prompt_format =
11441b654882SGreg Clayton     "{addr = '${addr}'\n}"
1145aff1b357SJason Molenda     "{addr-file-or-load = '${addr-file-or-load}'\n}"
1146aff1b357SJason Molenda     "{current-pc-arrow = '${current-pc-arrow}'\n}"
11471b654882SGreg Clayton     "{process.id = '${process.id}'\n}"
11481b654882SGreg Clayton     "{process.name = '${process.name}'\n}"
11491b654882SGreg Clayton     "{process.file.basename = '${process.file.basename}'\n}"
11501b654882SGreg Clayton     "{process.file.fullpath = '${process.file.fullpath}'\n}"
11511b654882SGreg Clayton     "{thread.id = '${thread.id}'\n}"
11521b654882SGreg Clayton     "{thread.index = '${thread.index}'\n}"
11531b654882SGreg Clayton     "{thread.name = '${thread.name}'\n}"
11541b654882SGreg Clayton     "{thread.queue = '${thread.queue}'\n}"
11551b654882SGreg Clayton     "{thread.stop-reason = '${thread.stop-reason}'\n}"
11561b654882SGreg Clayton     "{target.arch = '${target.arch}'\n}"
11571b654882SGreg Clayton     "{module.file.basename = '${module.file.basename}'\n}"
11581b654882SGreg Clayton     "{module.file.fullpath = '${module.file.fullpath}'\n}"
11591b654882SGreg Clayton     "{file.basename = '${file.basename}'\n}"
11601b654882SGreg Clayton     "{file.fullpath = '${file.fullpath}'\n}"
11611b654882SGreg Clayton     "{frame.index = '${frame.index}'\n}"
11621b654882SGreg Clayton     "{frame.pc = '${frame.pc}'\n}"
11631b654882SGreg Clayton     "{frame.sp = '${frame.sp}'\n}"
11641b654882SGreg Clayton     "{frame.fp = '${frame.fp}'\n}"
11651b654882SGreg Clayton     "{frame.flags = '${frame.flags}'\n}"
11661b654882SGreg Clayton     "{frame.reg.rdi = '${frame.reg.rdi}'\n}"
11671b654882SGreg Clayton     "{frame.reg.rip = '${frame.reg.rip}'\n}"
11681b654882SGreg Clayton     "{frame.reg.rsp = '${frame.reg.rsp}'\n}"
11691b654882SGreg Clayton     "{frame.reg.rbp = '${frame.reg.rbp}'\n}"
11701b654882SGreg Clayton     "{frame.reg.rflags = '${frame.reg.rflags}'\n}"
11711b654882SGreg Clayton     "{frame.reg.xmm0 = '${frame.reg.xmm0}'\n}"
11721b654882SGreg Clayton     "{frame.reg.carp = '${frame.reg.carp}'\n}"
11731b654882SGreg Clayton     "{function.id = '${function.id}'\n}"
1174aff1b357SJason Molenda     "{function.changed = '${function.changed}'\n}"
1175aff1b357SJason Molenda     "{function.initial-function = '${function.initial-function}'\n}"
11761b654882SGreg Clayton     "{function.name = '${function.name}'\n}"
1177aff1b357SJason Molenda     "{function.name-without-args = '${function.name-without-args}'\n}"
1178ccbc08e6SGreg Clayton     "{function.name-with-args = '${function.name-with-args}'\n}"
11791b654882SGreg Clayton     "{function.addr-offset = '${function.addr-offset}'\n}"
1180aff1b357SJason Molenda     "{function.concrete-only-addr-offset-no-padding = '${function.concrete-only-addr-offset-no-padding}'\n}"
11811b654882SGreg Clayton     "{function.line-offset = '${function.line-offset}'\n}"
11821b654882SGreg Clayton     "{function.pc-offset = '${function.pc-offset}'\n}"
11831b654882SGreg Clayton     "{line.file.basename = '${line.file.basename}'\n}"
11841b654882SGreg Clayton     "{line.file.fullpath = '${line.file.fullpath}'\n}"
11851b654882SGreg Clayton     "{line.number = '${line.number}'\n}"
11861b654882SGreg Clayton     "{line.start-addr = '${line.start-addr}'\n}"
11871b654882SGreg Clayton     "{line.end-addr = '${line.end-addr}'\n}"
11881b654882SGreg Clayton ;
11891b654882SGreg Clayton 
11901b654882SGreg Clayton     SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
11911b654882SGreg Clayton     ExecutionContext exe_ctx;
11920603aa9dSGreg Clayton     frame->CalculateExecutionContext(exe_ctx);
1193c3ce7f27SMichael Sartain     if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s))
11941b654882SGreg Clayton     {
11951b654882SGreg Clayton         printf("%s\n", s.GetData());
11961b654882SGreg Clayton     }
11971b654882SGreg Clayton     else
11981b654882SGreg Clayton     {
11991b654882SGreg Clayton         printf ("what we got: %s\n", s.GetData());
12001b654882SGreg Clayton     }
12011b654882SGreg Clayton }
12022643b905SSaleem Abdulrasool #endif
12031b654882SGreg Clayton 
1204b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format,
1205aff1b357SJason Molenda                                          const SymbolContext *sc,
1206aff1b357SJason Molenda                                          const SymbolContext *prev_sc,
1207aff1b357SJason Molenda                                          const ExecutionContext *exe_ctx,
1208b9c1b51eSKate Stone                                          const Address *addr, Stream &s) {
1209554f68d3SGreg Clayton   FormatEntity::Entry format_entry;
1210554f68d3SGreg Clayton 
1211b9c1b51eSKate Stone   if (format == nullptr) {
1212df370550SEugene Zelenko     if (exe_ctx != nullptr && exe_ctx->HasTargetScope())
1213aff1b357SJason Molenda       format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat();
1214b9c1b51eSKate Stone     if (format == nullptr) {
1215554f68d3SGreg Clayton       FormatEntity::Parse("${addr}: ", format_entry);
1216554f68d3SGreg Clayton       format = &format_entry;
1217554f68d3SGreg Clayton     }
1218aff1b357SJason Molenda   }
1219aff1b357SJason Molenda   bool function_changed = false;
1220aff1b357SJason Molenda   bool initial_function = false;
1221b9c1b51eSKate Stone   if (prev_sc && (prev_sc->function || prev_sc->symbol)) {
1222b9c1b51eSKate Stone     if (sc && (sc->function || sc->symbol)) {
1223b9c1b51eSKate Stone       if (prev_sc->symbol && sc->symbol) {
1224b9c1b51eSKate Stone         if (!sc->symbol->Compare(prev_sc->symbol->GetName(),
1225b9c1b51eSKate Stone                                  prev_sc->symbol->GetType())) {
1226aff1b357SJason Molenda           function_changed = true;
1227aff1b357SJason Molenda         }
1228b9c1b51eSKate Stone       } else if (prev_sc->function && sc->function) {
1229b9c1b51eSKate Stone         if (prev_sc->function->GetMangled() != sc->function->GetMangled()) {
1230aff1b357SJason Molenda           function_changed = true;
1231aff1b357SJason Molenda         }
1232aff1b357SJason Molenda       }
1233aff1b357SJason Molenda     }
1234aff1b357SJason Molenda   }
1235aff1b357SJason Molenda   // The first context on a list of instructions will have a prev_sc that
1236aff1b357SJason Molenda   // has no Function or Symbol -- if SymbolContext had an IsValid() method, it
1237aff1b357SJason Molenda   // would return false.  But we do get a prev_sc pointer.
1238b9c1b51eSKate Stone   if ((sc && (sc->function || sc->symbol)) && prev_sc &&
1239b9c1b51eSKate Stone       (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) {
1240aff1b357SJason Molenda     initial_function = true;
1241aff1b357SJason Molenda   }
1242b9c1b51eSKate Stone   return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr,
1243b9c1b51eSKate Stone                               function_changed, initial_function);
1244aff1b357SJason Molenda }
1245aff1b357SJason Molenda 
1246b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback,
1247b9c1b51eSKate Stone                                   void *baton) {
12484f02b22dSJim Ingham   // For simplicity's sake, I am not going to deal with how to close down any
12494f02b22dSJim Ingham   // open logging streams, I just redirect everything from here on out to the
12504f02b22dSJim Ingham   // callback.
1251*2f3df613SZachary Turner   m_log_callback_stream_sp =
1252*2f3df613SZachary Turner       std::make_shared<StreamCallback>(log_callback, baton);
1253228063cdSJim Ingham }
1254228063cdSJim Ingham 
12555e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel,
12565e336903SPavel Labath                          llvm::ArrayRef<const char *> categories,
12575e336903SPavel Labath                          llvm::StringRef log_file, uint32_t log_options,
1258775588c0SPavel Labath                          llvm::raw_ostream &error_stream) {
12595fae71c5SPavel Labath   const bool should_close = true;
12605fae71c5SPavel Labath   const bool unbuffered = true;
12615fae71c5SPavel Labath 
12625fae71c5SPavel Labath   std::shared_ptr<llvm::raw_ostream> log_stream_sp;
1263b9c1b51eSKate Stone   if (m_log_callback_stream_sp) {
1264228063cdSJim Ingham     log_stream_sp = m_log_callback_stream_sp;
1265228063cdSJim Ingham     // For now when using the callback mode you always get thread & timestamp.
1266b9c1b51eSKate Stone     log_options |=
1267b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME;
12685e336903SPavel Labath   } else if (log_file.empty()) {
12695fae71c5SPavel Labath     log_stream_sp = std::make_shared<llvm::raw_fd_ostream>(
12705fae71c5SPavel Labath         GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered);
1271b9c1b51eSKate Stone   } else {
12725fae71c5SPavel Labath     auto pos = m_log_streams.find(log_file);
1273c1b2ccfdSGreg Clayton     if (pos != m_log_streams.end())
1274c1b2ccfdSGreg Clayton       log_stream_sp = pos->second.lock();
1275b9c1b51eSKate Stone     if (!log_stream_sp) {
12765fae71c5SPavel Labath       llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text;
12775fae71c5SPavel Labath       if (log_options & LLDB_LOG_OPTION_APPEND)
12785fae71c5SPavel Labath         flags |= llvm::sys::fs::F_Append;
12795fae71c5SPavel Labath       int FD;
12805fae71c5SPavel Labath       if (std::error_code ec =
12815fae71c5SPavel Labath               llvm::sys::fs::openFileForWrite(log_file, FD, flags)) {
1282775588c0SPavel Labath         error_stream << "Unable to open log file: " << ec.message();
12835fae71c5SPavel Labath         return false;
12845fae71c5SPavel Labath       }
1285*2f3df613SZachary Turner       log_stream_sp =
1286*2f3df613SZachary Turner           std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered);
1287228063cdSJim Ingham       m_log_streams[log_file] = log_stream_sp;
1288228063cdSJim Ingham     }
1289228063cdSJim Ingham   }
1290df370550SEugene Zelenko   assert(log_stream_sp);
1291228063cdSJim Ingham 
1292228063cdSJim Ingham   if (log_options == 0)
1293b9c1b51eSKate Stone     log_options =
1294b9c1b51eSKate Stone         LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
1295228063cdSJim Ingham 
1296b9c1b51eSKate Stone   return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories,
1297b9c1b51eSKate Stone                                error_stream);
1298228063cdSJim Ingham }
1299228063cdSJim Ingham 
1300b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() {
1301df370550SEugene Zelenko   if (!m_source_manager_ap)
1302*2f3df613SZachary Turner     m_source_manager_ap = llvm::make_unique<SourceManager>(shared_from_this());
13039585fbfcSGreg Clayton   return *m_source_manager_ap;
13049585fbfcSGreg Clayton }
13059585fbfcSGreg Clayton 
130644d93782SGreg Clayton // This function handles events that were broadcast by the process.
1307b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) {
130844d93782SGreg Clayton   using namespace lldb;
1309b9c1b51eSKate Stone   const uint32_t event_type =
1310b9c1b51eSKate Stone       Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(
1311b9c1b51eSKate Stone           event_sp);
131244d93782SGreg Clayton 
131344d93782SGreg Clayton   //    if (event_type & eBreakpointEventTypeAdded
131444d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeRemoved
131544d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeEnabled
131644d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeDisabled
131744d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeCommandChanged
131844d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeConditionChanged
131944d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeIgnoreChanged
132044d93782SGreg Clayton   //        || event_type & eBreakpointEventTypeLocationsResolved)
132144d93782SGreg Clayton   //    {
1322b9c1b51eSKate Stone   //        // Don't do anything about these events, since the breakpoint
1323b9c1b51eSKate Stone   //        commands already echo these actions.
132444d93782SGreg Clayton   //    }
132544d93782SGreg Clayton   //
1326b9c1b51eSKate Stone   if (event_type & eBreakpointEventTypeLocationsAdded) {
1327b9c1b51eSKate Stone     uint32_t num_new_locations =
1328b9c1b51eSKate Stone         Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(
1329b9c1b51eSKate Stone             event_sp);
1330b9c1b51eSKate Stone     if (num_new_locations > 0) {
1331b9c1b51eSKate Stone       BreakpointSP breakpoint =
1332b9c1b51eSKate Stone           Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp);
13334446487dSPavel Labath       StreamSP output_sp(GetAsyncOutputStream());
1334b9c1b51eSKate Stone       if (output_sp) {
133544d93782SGreg Clayton         output_sp->Printf("%d location%s added to breakpoint %d\n",
1336b9c1b51eSKate Stone                           num_new_locations, num_new_locations == 1 ? "" : "s",
133744d93782SGreg Clayton                           breakpoint->GetID());
13384446487dSPavel Labath         output_sp->Flush();
133944d93782SGreg Clayton       }
134044d93782SGreg Clayton     }
134144d93782SGreg Clayton   }
134244d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsRemoved)
134344d93782SGreg Clayton   //    {
1344b9c1b51eSKate Stone   //        // These locations just get disabled, not sure it is worth spamming
1345b9c1b51eSKate Stone   //        folks about this on the command line.
134644d93782SGreg Clayton   //    }
134744d93782SGreg Clayton   //    else if (event_type & eBreakpointEventTypeLocationsResolved)
134844d93782SGreg Clayton   //    {
1349b9c1b51eSKate Stone   //        // This might be an interesting thing to note, but I'm going to
1350b9c1b51eSKate Stone   //        leave it quiet for now, it just looked noisy.
135144d93782SGreg Clayton   //    }
135244d93782SGreg Clayton }
135344d93782SGreg Clayton 
1354b9c1b51eSKate Stone size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) {
135544d93782SGreg Clayton   size_t total_bytes = 0;
1356df370550SEugene Zelenko   if (stream == nullptr)
135744d93782SGreg Clayton     stream = GetOutputFile().get();
135844d93782SGreg Clayton 
1359b9c1b51eSKate Stone   if (stream) {
1360b9c1b51eSKate Stone     //  The process has stuff waiting for stdout; get it and write it out to the
1361b9c1b51eSKate Stone     //  appropriate place.
1362b9c1b51eSKate Stone     if (process == nullptr) {
136344d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
136444d93782SGreg Clayton       if (target_sp)
136544d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
136644d93782SGreg Clayton     }
1367b9c1b51eSKate Stone     if (process) {
136844d93782SGreg Clayton       Error error;
136944d93782SGreg Clayton       size_t len;
137044d93782SGreg Clayton       char stdio_buffer[1024];
1371b9c1b51eSKate Stone       while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer),
1372b9c1b51eSKate Stone                                        error)) > 0) {
137344d93782SGreg Clayton         stream->Write(stdio_buffer, len);
137444d93782SGreg Clayton         total_bytes += len;
137544d93782SGreg Clayton       }
137644d93782SGreg Clayton     }
137744d93782SGreg Clayton     stream->Flush();
137844d93782SGreg Clayton   }
137944d93782SGreg Clayton   return total_bytes;
138044d93782SGreg Clayton }
138144d93782SGreg Clayton 
1382b9c1b51eSKate Stone size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) {
138344d93782SGreg Clayton   size_t total_bytes = 0;
1384df370550SEugene Zelenko   if (stream == nullptr)
138544d93782SGreg Clayton     stream = GetOutputFile().get();
138644d93782SGreg Clayton 
1387b9c1b51eSKate Stone   if (stream) {
1388b9c1b51eSKate Stone     //  The process has stuff waiting for stderr; get it and write it out to the
1389b9c1b51eSKate Stone     //  appropriate place.
1390b9c1b51eSKate Stone     if (process == nullptr) {
139144d93782SGreg Clayton       TargetSP target_sp = GetTargetList().GetSelectedTarget();
139244d93782SGreg Clayton       if (target_sp)
139344d93782SGreg Clayton         process = target_sp->GetProcessSP().get();
139444d93782SGreg Clayton     }
1395b9c1b51eSKate Stone     if (process) {
139644d93782SGreg Clayton       Error error;
139744d93782SGreg Clayton       size_t len;
139844d93782SGreg Clayton       char stdio_buffer[1024];
1399b9c1b51eSKate Stone       while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer),
1400b9c1b51eSKate Stone                                        error)) > 0) {
140144d93782SGreg Clayton         stream->Write(stdio_buffer, len);
140244d93782SGreg Clayton         total_bytes += len;
140344d93782SGreg Clayton       }
140444d93782SGreg Clayton     }
140544d93782SGreg Clayton     stream->Flush();
140644d93782SGreg Clayton   }
140744d93782SGreg Clayton   return total_bytes;
140844d93782SGreg Clayton }
140944d93782SGreg Clayton 
141044d93782SGreg Clayton // This function handles events that were broadcast by the process.
1411b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) {
141244d93782SGreg Clayton   using namespace lldb;
141344d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
1414b9c1b51eSKate Stone   ProcessSP process_sp =
1415b9c1b51eSKate Stone       (event_type == Process::eBroadcastBitStructuredData)
141675930019STodd Fiala           ? EventDataStructuredData::GetProcessFromEvent(event_sp.get())
141775930019STodd Fiala           : Process::ProcessEventData::GetProcessFromEvent(event_sp.get());
141844d93782SGreg Clayton 
14194446487dSPavel Labath   StreamSP output_stream_sp = GetAsyncOutputStream();
14204446487dSPavel Labath   StreamSP error_stream_sp = GetAsyncErrorStream();
142144d93782SGreg Clayton   const bool gui_enabled = IsForwardingEvents();
142244d93782SGreg Clayton 
1423b9c1b51eSKate Stone   if (!gui_enabled) {
1424b4874f1aSGreg Clayton     bool pop_process_io_handler = false;
142544d93782SGreg Clayton     assert(process_sp);
142644d93782SGreg Clayton 
14274446487dSPavel Labath     bool state_is_stopped = false;
1428b9c1b51eSKate Stone     const bool got_state_changed =
1429b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStateChanged) != 0;
14304446487dSPavel Labath     const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0;
14314446487dSPavel Labath     const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0;
1432b9c1b51eSKate Stone     const bool got_structured_data =
1433b9c1b51eSKate Stone         (event_type & Process::eBroadcastBitStructuredData) != 0;
143475930019STodd Fiala 
1435b9c1b51eSKate Stone     if (got_state_changed) {
1436b9c1b51eSKate Stone       StateType event_state =
1437b9c1b51eSKate Stone           Process::ProcessEventData::GetStateFromEvent(event_sp.get());
14384446487dSPavel Labath       state_is_stopped = StateIsStoppedState(event_state, false);
143944d93782SGreg Clayton     }
1440b4874f1aSGreg Clayton 
14414446487dSPavel Labath     // Display running state changes first before any STDIO
1442b9c1b51eSKate Stone     if (got_state_changed && !state_is_stopped) {
1443b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1444b9c1b51eSKate Stone                                               pop_process_io_handler);
144544d93782SGreg Clayton     }
1446b4874f1aSGreg Clayton 
14474446487dSPavel Labath     // Now display and STDOUT
1448b9c1b51eSKate Stone     if (got_stdout || got_state_changed) {
14494446487dSPavel Labath       GetProcessSTDOUT(process_sp.get(), output_stream_sp.get());
145044d93782SGreg Clayton     }
1451b4874f1aSGreg Clayton 
14524446487dSPavel Labath     // Now display and STDERR
1453b9c1b51eSKate Stone     if (got_stderr || got_state_changed) {
14544446487dSPavel Labath       GetProcessSTDERR(process_sp.get(), error_stream_sp.get());
1455b4874f1aSGreg Clayton     }
1456b4874f1aSGreg Clayton 
145775930019STodd Fiala     // Give structured data events an opportunity to display.
1458b9c1b51eSKate Stone     if (got_structured_data) {
145975930019STodd Fiala       StructuredDataPluginSP plugin_sp =
146075930019STodd Fiala           EventDataStructuredData::GetPluginFromEvent(event_sp.get());
1461b9c1b51eSKate Stone       if (plugin_sp) {
146275930019STodd Fiala         auto structured_data_sp =
146375930019STodd Fiala             EventDataStructuredData::GetObjectFromEvent(event_sp.get());
1464b9c1b51eSKate Stone         if (output_stream_sp) {
146575930019STodd Fiala           StreamString content_stream;
1466b9c1b51eSKate Stone           Error error =
1467b9c1b51eSKate Stone               plugin_sp->GetDescription(structured_data_sp, content_stream);
1468b9c1b51eSKate Stone           if (error.Success()) {
1469b9c1b51eSKate Stone             if (!content_stream.GetString().empty()) {
147075930019STodd Fiala               // Add newline.
147175930019STodd Fiala               content_stream.PutChar('\n');
147275930019STodd Fiala               content_stream.Flush();
147375930019STodd Fiala 
147475930019STodd Fiala               // Print it.
1475771ef6d4SMalcolm Parsons               output_stream_sp->PutCString(content_stream.GetString());
147675930019STodd Fiala             }
1477b9c1b51eSKate Stone           } else {
147875930019STodd Fiala             error_stream_sp->Printf("Failed to print structured "
147975930019STodd Fiala                                     "data with plugin %s: %s",
1480b9c1b51eSKate Stone                                     plugin_sp->GetPluginName().AsCString(),
148175930019STodd Fiala                                     error.AsCString());
148275930019STodd Fiala           }
148375930019STodd Fiala         }
148475930019STodd Fiala       }
148575930019STodd Fiala     }
148675930019STodd Fiala 
14874446487dSPavel Labath     // Now display any stopped state changes after any STDIO
1488b9c1b51eSKate Stone     if (got_state_changed && state_is_stopped) {
1489b9c1b51eSKate Stone       Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(),
1490b9c1b51eSKate Stone                                               pop_process_io_handler);
149144d93782SGreg Clayton     }
149244d93782SGreg Clayton 
14934446487dSPavel Labath     output_stream_sp->Flush();
14944446487dSPavel Labath     error_stream_sp->Flush();
149544d93782SGreg Clayton 
1496b4874f1aSGreg Clayton     if (pop_process_io_handler)
1497b4874f1aSGreg Clayton       process_sp->PopProcessIOHandler();
1498b4874f1aSGreg Clayton   }
1499b4874f1aSGreg Clayton }
1500b4874f1aSGreg Clayton 
1501b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) {
150244d93782SGreg Clayton   // At present the only thread event we handle is the Frame Changed event,
150344d93782SGreg Clayton   // and all we do for that is just reprint the thread status for that thread.
150444d93782SGreg Clayton   using namespace lldb;
150544d93782SGreg Clayton   const uint32_t event_type = event_sp->GetType();
15066a9767c7SJim Ingham   const bool stop_format = true;
150744d93782SGreg Clayton   if (event_type == Thread::eBroadcastBitStackChanged ||
1508b9c1b51eSKate Stone       event_type == Thread::eBroadcastBitThreadSelected) {
1509b9c1b51eSKate Stone     ThreadSP thread_sp(
1510b9c1b51eSKate Stone         Thread::ThreadEventData::GetThreadFromEvent(event_sp.get()));
1511b9c1b51eSKate Stone     if (thread_sp) {
15126a9767c7SJim Ingham       thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format);
151344d93782SGreg Clayton     }
151444d93782SGreg Clayton   }
151544d93782SGreg Clayton }
151644d93782SGreg Clayton 
1517b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; }
151844d93782SGreg Clayton 
1519b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) {
152044d93782SGreg Clayton   m_forward_listener_sp = listener_sp;
152144d93782SGreg Clayton }
152244d93782SGreg Clayton 
1523b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) {
152444d93782SGreg Clayton   m_forward_listener_sp.reset();
152544d93782SGreg Clayton }
152644d93782SGreg Clayton 
1527b9c1b51eSKate Stone void Debugger::DefaultEventHandler() {
1528583bbb1dSJim Ingham   ListenerSP listener_sp(GetListener());
152944d93782SGreg Clayton   ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass());
153044d93782SGreg Clayton   ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass());
153144d93782SGreg Clayton   ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass());
153244d93782SGreg Clayton   BroadcastEventSpec target_event_spec(broadcaster_class_target,
153344d93782SGreg Clayton                                        Target::eBroadcastBitBreakpointChanged);
153444d93782SGreg Clayton 
1535b9c1b51eSKate Stone   BroadcastEventSpec process_event_spec(
1536b9c1b51eSKate Stone       broadcaster_class_process,
1537b9c1b51eSKate Stone       Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT |
1538b9c1b51eSKate Stone           Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData);
153944d93782SGreg Clayton 
154044d93782SGreg Clayton   BroadcastEventSpec thread_event_spec(broadcaster_class_thread,
154144d93782SGreg Clayton                                        Thread::eBroadcastBitStackChanged |
154244d93782SGreg Clayton                                            Thread::eBroadcastBitThreadSelected);
154344d93782SGreg Clayton 
1544b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1545b9c1b51eSKate Stone                                           target_event_spec);
1546b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1547b9c1b51eSKate Stone                                           process_event_spec);
1548b9c1b51eSKate Stone   listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp,
1549b9c1b51eSKate Stone                                           thread_event_spec);
1550b9c1b51eSKate Stone   listener_sp->StartListeningForEvents(
1551b9c1b51eSKate Stone       m_command_interpreter_ap.get(),
155244d93782SGreg Clayton       CommandInterpreter::eBroadcastBitQuitCommandReceived |
155344d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousOutputData |
155444d93782SGreg Clayton           CommandInterpreter::eBroadcastBitAsynchronousErrorData);
155544d93782SGreg Clayton 
1556afa91e33SGreg Clayton   // Let the thread that spawned us know that we have started up and
1557afa91e33SGreg Clayton   // that we are now listening to all required events so no events get missed
1558afa91e33SGreg Clayton   m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening);
1559afa91e33SGreg Clayton 
156044d93782SGreg Clayton   bool done = false;
1561b9c1b51eSKate Stone   while (!done) {
156244d93782SGreg Clayton     EventSP event_sp;
1563d35031e1SPavel Labath     if (listener_sp->GetEvent(event_sp, llvm::None)) {
1564b9c1b51eSKate Stone       if (event_sp) {
156544d93782SGreg Clayton         Broadcaster *broadcaster = event_sp->GetBroadcaster();
1566b9c1b51eSKate Stone         if (broadcaster) {
156744d93782SGreg Clayton           uint32_t event_type = event_sp->GetType();
156844d93782SGreg Clayton           ConstString broadcaster_class(broadcaster->GetBroadcasterClass());
1569b9c1b51eSKate Stone           if (broadcaster_class == broadcaster_class_process) {
157044d93782SGreg Clayton             HandleProcessEvent(event_sp);
1571b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_target) {
1572b9c1b51eSKate Stone             if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(
1573b9c1b51eSKate Stone                     event_sp.get())) {
157444d93782SGreg Clayton               HandleBreakpointEvent(event_sp);
157544d93782SGreg Clayton             }
1576b9c1b51eSKate Stone           } else if (broadcaster_class == broadcaster_class_thread) {
157744d93782SGreg Clayton             HandleThreadEvent(event_sp);
1578b9c1b51eSKate Stone           } else if (broadcaster == m_command_interpreter_ap.get()) {
1579b9c1b51eSKate Stone             if (event_type &
1580b9c1b51eSKate Stone                 CommandInterpreter::eBroadcastBitQuitCommandReceived) {
158144d93782SGreg Clayton               done = true;
1582b9c1b51eSKate Stone             } else if (event_type &
1583b9c1b51eSKate Stone                        CommandInterpreter::eBroadcastBitAsynchronousErrorData) {
1584b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1585b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1586b9c1b51eSKate Stone               if (data && data[0]) {
15874446487dSPavel Labath                 StreamSP error_sp(GetAsyncErrorStream());
1588b9c1b51eSKate Stone                 if (error_sp) {
158944d93782SGreg Clayton                   error_sp->PutCString(data);
159044d93782SGreg Clayton                   error_sp->Flush();
159144d93782SGreg Clayton                 }
159244d93782SGreg Clayton               }
1593b9c1b51eSKate Stone             } else if (event_type & CommandInterpreter::
1594b9c1b51eSKate Stone                                         eBroadcastBitAsynchronousOutputData) {
1595b9c1b51eSKate Stone               const char *data = reinterpret_cast<const char *>(
1596b9c1b51eSKate Stone                   EventDataBytes::GetBytesFromEvent(event_sp.get()));
1597b9c1b51eSKate Stone               if (data && data[0]) {
15984446487dSPavel Labath                 StreamSP output_sp(GetAsyncOutputStream());
1599b9c1b51eSKate Stone                 if (output_sp) {
160044d93782SGreg Clayton                   output_sp->PutCString(data);
160144d93782SGreg Clayton                   output_sp->Flush();
160244d93782SGreg Clayton                 }
160344d93782SGreg Clayton               }
160444d93782SGreg Clayton             }
160544d93782SGreg Clayton           }
160644d93782SGreg Clayton         }
160744d93782SGreg Clayton 
160844d93782SGreg Clayton         if (m_forward_listener_sp)
160944d93782SGreg Clayton           m_forward_listener_sp->AddEvent(event_sp);
161044d93782SGreg Clayton       }
161144d93782SGreg Clayton     }
161244d93782SGreg Clayton   }
161344d93782SGreg Clayton }
161444d93782SGreg Clayton 
1615b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) {
161644d93782SGreg Clayton   ((Debugger *)arg)->DefaultEventHandler();
161744d93782SGreg Clayton   return NULL;
161844d93782SGreg Clayton }
161944d93782SGreg Clayton 
1620b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() {
1621b9c1b51eSKate Stone   if (!m_event_handler_thread.IsJoinable()) {
1622afa91e33SGreg Clayton     // We must synchronize with the DefaultEventHandler() thread to ensure
1623afa91e33SGreg Clayton     // it is up and running and listening to events before we return from
1624afa91e33SGreg Clayton     // this function. We do this by listening to events for the
1625afa91e33SGreg Clayton     // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster
1626b9c1b51eSKate Stone     ListenerSP listener_sp(
1627b9c1b51eSKate Stone         Listener::MakeListener("lldb.debugger.event-handler"));
1628b9c1b51eSKate Stone     listener_sp->StartListeningForEvents(&m_sync_broadcaster,
1629b9c1b51eSKate Stone                                          eBroadcastBitEventThreadIsListening);
1630afa91e33SGreg Clayton 
16317c2896a2SZachary Turner     // Use larger 8MB stack for this thread
1632b9c1b51eSKate Stone     m_event_handler_thread = ThreadLauncher::LaunchThread(
1633b9c1b51eSKate Stone         "lldb.debugger.event-handler", EventHandlerThread, this, nullptr,
16347c2896a2SZachary Turner         g_debugger_event_thread_stack_bytes);
1635afa91e33SGreg Clayton 
1636b9c1b51eSKate Stone     // Make sure DefaultEventHandler() is running and listening to events before
1637b9c1b51eSKate Stone     // we return
1638afa91e33SGreg Clayton     // from this function. We are only listening for events of type
1639b9c1b51eSKate Stone     // eBroadcastBitEventThreadIsListening so we don't need to check the event,
1640b9c1b51eSKate Stone     // we just need
1641b9c1b51eSKate Stone     // to wait an infinite amount of time for it (nullptr timeout as the first
1642b9c1b51eSKate Stone     // parameter)
1643afa91e33SGreg Clayton     lldb::EventSP event_sp;
1644d35031e1SPavel Labath     listener_sp->GetEvent(event_sp, llvm::None);
1645807b6b32SGreg Clayton   }
1646acee96aeSZachary Turner   return m_event_handler_thread.IsJoinable();
164744d93782SGreg Clayton }
164844d93782SGreg Clayton 
1649b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() {
1650b9c1b51eSKate Stone   if (m_event_handler_thread.IsJoinable()) {
1651b9c1b51eSKate Stone     GetCommandInterpreter().BroadcastEvent(
1652b9c1b51eSKate Stone         CommandInterpreter::eBroadcastBitQuitCommandReceived);
165339de3110SZachary Turner     m_event_handler_thread.Join(nullptr);
165444d93782SGreg Clayton   }
165544d93782SGreg Clayton }
165644d93782SGreg Clayton 
1657b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) {
165844d93782SGreg Clayton   Debugger *debugger = (Debugger *)arg;
16599aaab558SSiva Chandra   debugger->ExecuteIOHandlers();
166044d93782SGreg Clayton   debugger->StopEventHandlerThread();
166144d93782SGreg Clayton   return NULL;
166244d93782SGreg Clayton }
166344d93782SGreg Clayton 
1664b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); }
16656681041dSSean Callanan 
1666b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() {
1667acee96aeSZachary Turner   if (!m_io_handler_thread.IsJoinable())
1668b9c1b51eSKate Stone     m_io_handler_thread = ThreadLauncher::LaunchThread(
1669b9c1b51eSKate Stone         "lldb.debugger.io-handler", IOHandlerThread, this, nullptr,
1670807b6b32SGreg Clayton         8 * 1024 * 1024); // Use larger 8MB stack for this thread
1671acee96aeSZachary Turner   return m_io_handler_thread.IsJoinable();
167244d93782SGreg Clayton }
167344d93782SGreg Clayton 
1674b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() {
1675b9c1b51eSKate Stone   if (m_io_handler_thread.IsJoinable()) {
167644d93782SGreg Clayton     if (m_input_file_sp)
167744d93782SGreg Clayton       m_input_file_sp->GetFile().Close();
167839de3110SZachary Turner     m_io_handler_thread.Join(nullptr);
167944d93782SGreg Clayton   }
168044d93782SGreg Clayton }
168144d93782SGreg Clayton 
1682b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() {
1683b9c1b51eSKate Stone   if (HasIOHandlerThread()) {
16846681041dSSean Callanan     thread_result_t result;
16856681041dSSean Callanan     m_io_handler_thread.Join(&result);
16866681041dSSean Callanan     m_io_handler_thread = LLDB_INVALID_HOST_THREAD;
16876681041dSSean Callanan   }
16886681041dSSean Callanan }
16896681041dSSean Callanan 
1690b9c1b51eSKate Stone Target *Debugger::GetDummyTarget() {
1691893c932aSJim Ingham   return m_target_list.GetDummyTarget(*this).get();
1692893c932aSJim Ingham }
1693893c932aSJim Ingham 
1694b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) {
169533df7cd3SJim Ingham   Target *target = nullptr;
1696b9c1b51eSKate Stone   if (!prefer_dummy) {
169733df7cd3SJim Ingham     target = m_target_list.GetSelectedTarget().get();
169833df7cd3SJim Ingham     if (target)
169933df7cd3SJim Ingham       return target;
170033df7cd3SJim Ingham   }
1701893c932aSJim Ingham 
1702893c932aSJim Ingham   return GetDummyTarget();
1703893c932aSJim Ingham }
170444d93782SGreg Clayton 
1705b9c1b51eSKate Stone Error Debugger::RunREPL(LanguageType language, const char *repl_options) {
17063e7e915dSSean Callanan   Error err;
17073e7e915dSSean Callanan   FileSpec repl_executable;
17083e7e915dSSean Callanan 
1709b9c1b51eSKate Stone   if (language == eLanguageTypeUnknown) {
171097f84e87SSean Callanan     std::set<LanguageType> repl_languages;
171197f84e87SSean Callanan 
171297f84e87SSean Callanan     Language::GetLanguagesSupportingREPLs(repl_languages);
171397f84e87SSean Callanan 
1714b9c1b51eSKate Stone     if (repl_languages.size() == 1) {
171597f84e87SSean Callanan       language = *repl_languages.begin();
1716b9c1b51eSKate Stone     } else if (repl_languages.empty()) {
1717b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1718b9c1b51eSKate Stone           "LLDB isn't configured with REPL support for any languages.");
171997f84e87SSean Callanan       return err;
1720b9c1b51eSKate Stone     } else {
1721b9c1b51eSKate Stone       err.SetErrorStringWithFormat(
1722b9c1b51eSKate Stone           "Multiple possible REPL languages.  Please specify a language.");
172397f84e87SSean Callanan       return err;
172497f84e87SSean Callanan     }
172597f84e87SSean Callanan   }
172697f84e87SSean Callanan 
1727b9c1b51eSKate Stone   Target *const target =
1728b9c1b51eSKate Stone       nullptr; // passing in an empty target means the REPL must create one
17293e7e915dSSean Callanan 
17303b682de6SSean Callanan   REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options));
17313e7e915dSSean Callanan 
1732b9c1b51eSKate Stone   if (!err.Success()) {
17333e7e915dSSean Callanan     return err;
17343e7e915dSSean Callanan   }
17353e7e915dSSean Callanan 
1736b9c1b51eSKate Stone   if (!repl_sp) {
1737b9c1b51eSKate Stone     err.SetErrorStringWithFormat("couldn't find a REPL for %s",
1738b9c1b51eSKate Stone                                  Language::GetNameForLanguageType(language));
17393e7e915dSSean Callanan     return err;
17403e7e915dSSean Callanan   }
17413e7e915dSSean Callanan 
17423e7e915dSSean Callanan   repl_sp->SetCompilerOptions(repl_options);
17433e7e915dSSean Callanan   repl_sp->RunLoop();
17443e7e915dSSean Callanan 
17453e7e915dSSean Callanan   return err;
17463e7e915dSSean Callanan }
1747