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