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