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