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