130fdc8d8SChris Lattner //===-- Debugger.cpp --------------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 630fdc8d8SChris Lattner // 730fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 830fdc8d8SChris Lattner 94a33d318SGreg Clayton #include "lldb/Core/Debugger.h" 104a33d318SGreg Clayton 11672d2c12SJonas Devlieghere #include "lldb/Breakpoint/Breakpoint.h" 12554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 13672d2c12SJonas Devlieghere #include "lldb/Core/Mangled.h" 14672d2c12SJonas Devlieghere #include "lldb/Core/ModuleList.h" 15e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h" 165b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h" 1744d93782SGreg Clayton #include "lldb/Core/StreamFile.h" 185548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h" 193e7e915dSSean Callanan #include "lldb/Expression/REPL.h" 20672d2c12SJonas Devlieghere #include "lldb/Host/File.h" 2135e4c84cSJonas Devlieghere #include "lldb/Host/FileSystem.h" 2242ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h" 23a3406614SGreg Clayton #include "lldb/Host/Terminal.h" 2439de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 256611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 26672d2c12SJonas Devlieghere #include "lldb/Interpreter/OptionValue.h" 27633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 2867cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h" 2967cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 30672d2c12SJonas Devlieghere #include "lldb/Interpreter/Property.h" 31672d2c12SJonas Devlieghere #include "lldb/Interpreter/ScriptInterpreter.h" 321f746071SGreg Clayton #include "lldb/Symbol/Function.h" 331f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 34672d2c12SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h" 353e7e915dSSean Callanan #include "lldb/Target/Language.h" 3630fdc8d8SChris Lattner #include "lldb/Target/Process.h" 3775930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h" 3884a53dfbSEnrico Granata #include "lldb/Target/Target.h" 39b9c1b51eSKate Stone #include "lldb/Target/TargetList.h" 4030fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 41672d2c12SJonas Devlieghere #include "lldb/Target/ThreadList.h" 425a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 43181b823bSPavel Labath #include "lldb/Utility/Event.h" 44181b823bSPavel Labath #include "lldb/Utility/Listener.h" 45672d2c12SJonas Devlieghere #include "lldb/Utility/Log.h" 469e046f02SJonas Devlieghere #include "lldb/Utility/Reproducer.h" 47d821c997SPavel Labath #include "lldb/Utility/State.h" 48672d2c12SJonas Devlieghere #include "lldb/Utility/Stream.h" 49fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h" 50bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 512f3df613SZachary Turner 52b1cb0b79SNico Weber #if defined(_WIN32) 53672d2c12SJonas Devlieghere #include "lldb/Host/windows/PosixApi.h" 548aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h" 552f3df613SZachary Turner #endif 562f3df613SZachary Turner 57672d2c12SJonas Devlieghere #include "llvm/ADT/None.h" 58672d2c12SJonas Devlieghere #include "llvm/ADT/STLExtras.h" 592f3df613SZachary Turner #include "llvm/ADT/StringRef.h" 60672d2c12SJonas Devlieghere #include "llvm/ADT/iterator.h" 612f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h" 622f3df613SZachary Turner #include "llvm/Support/FileSystem.h" 638aa23614SDavid Bolvansky #include "llvm/Support/Process.h" 642f3df613SZachary Turner #include "llvm/Support/Threading.h" 65672d2c12SJonas Devlieghere #include "llvm/Support/raw_ostream.h" 662f3df613SZachary Turner 67672d2c12SJonas Devlieghere #include <list> 68672d2c12SJonas Devlieghere #include <memory> 692f3df613SZachary Turner #include <mutex> 70672d2c12SJonas Devlieghere #include <set> 71672d2c12SJonas Devlieghere #include <stdio.h> 72672d2c12SJonas Devlieghere #include <stdlib.h> 73672d2c12SJonas Devlieghere #include <string.h> 74672d2c12SJonas Devlieghere #include <string> 75672d2c12SJonas Devlieghere #include <system_error> 762f3df613SZachary Turner 772f3df613SZachary Turner namespace lldb_private { 782f3df613SZachary Turner class Address; 792f3df613SZachary Turner } 8030fdc8d8SChris Lattner 8130fdc8d8SChris Lattner using namespace lldb; 8230fdc8d8SChris Lattner using namespace lldb_private; 8330fdc8d8SChris Lattner 84ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 857c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; 86ebc1bb27SCaroline Tice 871b654882SGreg Clayton #pragma mark Static Functions 881b654882SGreg Clayton 891b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 90b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr = 91b9c1b51eSKate Stone nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain 92b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr = 93b9c1b51eSKate Stone nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain 94e372b98dSGreg Clayton 958fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { 96*e063ecccSJonas Devlieghere { 97*e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNever, 98*e063ecccSJonas Devlieghere "never", 99*e063ecccSJonas Devlieghere "Never show disassembly when displaying a stop context.", 100*e063ecccSJonas Devlieghere }, 101*e063ecccSJonas Devlieghere { 102*e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoDebugInfo, 103*e063ecccSJonas Devlieghere "no-debuginfo", 104*e063ecccSJonas Devlieghere "Show disassembly when there is no debug information.", 105*e063ecccSJonas Devlieghere }, 106*e063ecccSJonas Devlieghere { 107*e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoSource, 108*e063ecccSJonas Devlieghere "no-source", 109*e063ecccSJonas Devlieghere "Show disassembly when there is no source information, or the source " 110*e063ecccSJonas Devlieghere "file " 111*e063ecccSJonas Devlieghere "is missing when displaying a stop context.", 112*e063ecccSJonas Devlieghere }, 113*e063ecccSJonas Devlieghere { 114*e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeAlways, 115*e063ecccSJonas Devlieghere "always", 116*e063ecccSJonas Devlieghere "Always show disassembly when displaying a stop context.", 117*e063ecccSJonas Devlieghere }, 118*e063ecccSJonas Devlieghere }; 119e372b98dSGreg Clayton 1208fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = { 121*e063ecccSJonas Devlieghere { 122*e063ecccSJonas Devlieghere eScriptLanguageNone, 123*e063ecccSJonas Devlieghere "none", 124*e063ecccSJonas Devlieghere "Disable scripting languages.", 125*e063ecccSJonas Devlieghere }, 126*e063ecccSJonas Devlieghere { 127*e063ecccSJonas Devlieghere eScriptLanguagePython, 128*e063ecccSJonas Devlieghere "python", 129*e063ecccSJonas Devlieghere "Select python as the default scripting language.", 130*e063ecccSJonas Devlieghere }, 131*e063ecccSJonas Devlieghere { 132*e063ecccSJonas Devlieghere eScriptLanguageDefault, 133*e063ecccSJonas Devlieghere "default", 134*e063ecccSJonas Devlieghere "Select the lldb default as the default scripting language.", 135*e063ecccSJonas Devlieghere }, 136*e063ecccSJonas Devlieghere }; 137e372b98dSGreg Clayton 138b9c1b51eSKate Stone #define MODULE_WITH_FUNC \ 139b9c1b51eSKate Stone "{ " \ 1406a9767c7SJim Ingham "${module.file.basename}{`${function.name-with-args}" \ 1416a9767c7SJim Ingham "{${frame.no-debug}${function.pc-offset}}}}" 1427f1c1211SPavel Labath 1437f1c1211SPavel Labath #define MODULE_WITH_FUNC_NO_ARGS \ 1447f1c1211SPavel Labath "{ " \ 1457f1c1211SPavel Labath "${module.file.basename}{`${function.name-without-args}" \ 1467f1c1211SPavel Labath "{${frame.no-debug}${function.pc-offset}}}}" 1477f1c1211SPavel Labath 1484954f6a5SAdrian Prantl #define FILE_AND_LINE \ 149f9626f27SJonas Devlieghere "{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}" \ 150f9626f27SJonas Devlieghere ":${ansi.fg.yellow}${line.number}${ansi.normal}" \ 151f9626f27SJonas Devlieghere "{:${ansi.fg.yellow}${line.column}${ansi.normal}}}" 152f9626f27SJonas Devlieghere 1536ab659a9SJason Molenda #define IS_OPTIMIZED "{${function.is-optimized} [opt]}" 15467cc0636SGreg Clayton 1554b36f791SVedant Kumar #define IS_ARTIFICIAL "{${frame.is-artificial} [artificial]}" 1564b36f791SVedant Kumar 157b9c1b51eSKate Stone #define DEFAULT_THREAD_FORMAT \ 158b9c1b51eSKate Stone "thread #${thread.index}: tid = ${thread.id%tid}" \ 159b9c1b51eSKate Stone "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE \ 160f9626f27SJonas Devlieghere "{, name = ${ansi.fg.green}'${thread.name}'${ansi.normal}}" \ 161f9626f27SJonas Devlieghere "{, queue = ${ansi.fg.green}'${thread.queue}'${ansi.normal}}" \ 162f9626f27SJonas Devlieghere "{, activity = " \ 163f9626f27SJonas Devlieghere "${ansi.fg.green}'${thread.info.activity.name}'${ansi.normal}}" \ 164705b1809SJason Molenda "{, ${thread.info.trace_messages} messages}" \ 165f9626f27SJonas Devlieghere "{, stop reason = ${ansi.fg.red}${thread.stop-reason}${ansi.normal}}" \ 16667cc0636SGreg Clayton "{\\nReturn value: ${thread.return-value}}" \ 16730fadafeSJim Ingham "{\\nCompleted expression: ${thread.completed-expression}}" \ 16867cc0636SGreg Clayton "\\n" 16967cc0636SGreg Clayton 1706a9767c7SJim Ingham #define DEFAULT_THREAD_STOP_FORMAT \ 1716a9767c7SJim Ingham "thread #${thread.index}{, name = '${thread.name}'}" \ 172f9626f27SJonas Devlieghere "{, queue = ${ansi.fg.green}'${thread.queue}'${ansi.normal}}" \ 173f9626f27SJonas Devlieghere "{, activity = " \ 174f9626f27SJonas Devlieghere "${ansi.fg.green}'${thread.info.activity.name}'${ansi.normal}}" \ 1756a9767c7SJim Ingham "{, ${thread.info.trace_messages} messages}" \ 176f9626f27SJonas Devlieghere "{, stop reason = ${ansi.fg.red}${thread.stop-reason}${ansi.normal}}" \ 1776a9767c7SJim Ingham "{\\nReturn value: ${thread.return-value}}" \ 1786a9767c7SJim Ingham "{\\nCompleted expression: ${thread.completed-expression}}" \ 1796a9767c7SJim Ingham "\\n" 1806a9767c7SJim Ingham 181b9c1b51eSKate Stone #define DEFAULT_FRAME_FORMAT \ 182f9626f27SJonas Devlieghere "frame #${frame.index}: " \ 183f9626f27SJonas Devlieghere "${ansi.fg.yellow}${frame.pc}${ansi.normal}" MODULE_WITH_FUNC FILE_AND_LINE \ 1844b36f791SVedant Kumar IS_OPTIMIZED IS_ARTIFICIAL "\\n" 18567cc0636SGreg Clayton 1867f1c1211SPavel Labath #define DEFAULT_FRAME_FORMAT_NO_ARGS \ 187f9626f27SJonas Devlieghere "frame #${frame.index}: " \ 188f9626f27SJonas Devlieghere "${ansi.fg.yellow}${frame.pc}${ansi.normal}" MODULE_WITH_FUNC_NO_ARGS \ 189f9626f27SJonas Devlieghere FILE_AND_LINE IS_OPTIMIZED IS_ARTIFICIAL "\\n" 1907f1c1211SPavel Labath 191c980fa92SJason Molenda // Three parts to this disassembly format specification: 192c980fa92SJason Molenda // 1. If this is a new function/symbol (no previous symbol/function), print 193c980fa92SJason Molenda // dylib`funcname:\n 194b9c1b51eSKate Stone // 2. If this is a symbol context change (different from previous 195b9c1b51eSKate Stone // symbol/function), print 196c980fa92SJason Molenda // dylib`funcname:\n 197c980fa92SJason Molenda // 3. print 198c980fa92SJason Molenda // address <+offset>: 199b9c1b51eSKate Stone #define DEFAULT_DISASSEMBLY_FORMAT \ 200b9c1b51eSKate Stone "{${function.initial-function}{${module.file.basename}`}{${function.name-" \ 201e43be156SJonas Devlieghere "without-args}}:\\n}{${function.changed}\\n{${module.file.basename}`}{${" \ 202e43be156SJonas Devlieghere "function.name-without-args}}:\\n}{${current-pc-arrow} " \ 203b9c1b51eSKate Stone "}${addr-file-or-load}{ " \ 204b9c1b51eSKate Stone "<${function.concrete-only-addr-offset-no-padding}>}: " 205c980fa92SJason Molenda 20605097246SAdrian Prantl // gdb's disassembly format can be emulated with ${current-pc-arrow}${addr- 20705097246SAdrian Prantl // file-or-load}{ <${function.name-without-args}${function.concrete-only-addr- 20805097246SAdrian Prantl // offset-no-padding}>}: 209c980fa92SJason Molenda 210c980fa92SJason Molenda // lldb's original format for disassembly would look like this format string - 21105097246SAdrian Prantl // {${function.initial-function}{${module.file.basename}`}{${function.name- 21205097246SAdrian Prantl // without- 21305097246SAdrian Prantl // args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name- 21405097246SAdrian Prantl // without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}: 215c980fa92SJason Molenda 2168fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement s_stop_show_column_values[] = { 217*e063ecccSJonas Devlieghere { 218*e063ecccSJonas Devlieghere eStopShowColumnAnsiOrCaret, 219*e063ecccSJonas Devlieghere "ansi-or-caret", 220*e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when color/ANSI " 221*e063ecccSJonas Devlieghere "mode is enabled; otherwise, fall back to using a text-only caret (^) " 222*e063ecccSJonas Devlieghere "as if \"caret-only\" mode was selected.", 223*e063ecccSJonas Devlieghere }, 224*e063ecccSJonas Devlieghere { 225*e063ecccSJonas Devlieghere eStopShowColumnAnsi, 226*e063ecccSJonas Devlieghere "ansi", 227*e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when running LLDB " 228*e063ecccSJonas Devlieghere "with color/ANSI enabled.", 229*e063ecccSJonas Devlieghere }, 230*e063ecccSJonas Devlieghere { 231*e063ecccSJonas Devlieghere eStopShowColumnCaret, 232*e063ecccSJonas Devlieghere "caret", 233*e063ecccSJonas Devlieghere "Highlight the stop column with a caret character (^) underneath the " 234*e063ecccSJonas Devlieghere "stop column. This method introduces a new line in source listings " 235*e063ecccSJonas Devlieghere "that display thread stop locations.", 236*e063ecccSJonas Devlieghere }, 237*e063ecccSJonas Devlieghere { 238*e063ecccSJonas Devlieghere eStopShowColumnNone, 239*e063ecccSJonas Devlieghere "none", 240*e063ecccSJonas Devlieghere "Do not highlight the stop column.", 241*e063ecccSJonas Devlieghere }, 242*e063ecccSJonas Devlieghere }; 2439666ba75STodd Fiala 244971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger 2456a253d37SJordan Rupprecht #include "CoreProperties.inc" 24667cc0636SGreg Clayton 247b9c1b51eSKate Stone enum { 248971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger 2496a253d37SJordan Rupprecht #include "CorePropertiesEnum.inc" 25067cc0636SGreg Clayton }; 25167cc0636SGreg Clayton 252df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr; 2534c05410fSGreg Clayton 25497206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, 2554c05410fSGreg Clayton VarSetOperationType op, 25697206d57SZachary Turner llvm::StringRef property_path, 25797206d57SZachary Turner llvm::StringRef value) { 258*e063ecccSJonas Devlieghere bool is_load_script = 259*e063ecccSJonas Devlieghere (property_path == "target.load-script-from-symbol-file"); 26031d97a5cSZachary Turner bool is_escape_non_printables = (property_path == "escape-non-printables"); 26184a53dfbSEnrico Granata TargetSP target_sp; 262397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 263b9c1b51eSKate Stone if (is_load_script && exe_ctx->GetTargetSP()) { 26484a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 265b9c1b51eSKate Stone load_script_old_value = 266b9c1b51eSKate Stone target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 26784a53dfbSEnrico Granata } 26897206d57SZachary Turner Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value)); 269b9c1b51eSKate Stone if (error.Success()) { 27084a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 271a8ea5955SJonas Devlieghere if (property_path == g_debugger_properties[ePropertyPrompt].name) { 272514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 273b9c1b51eSKate Stone std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes( 274b9c1b51eSKate Stone new_prompt, GetUseColor()); 275c3ce7f27SMichael Sartain if (str.length()) 276771ef6d4SMalcolm Parsons new_prompt = str; 27744d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 2782f3df613SZachary Turner auto bytes = llvm::make_unique<EventDataBytes>(new_prompt); 2792f3df613SZachary Turner auto prompt_change_event_sp = std::make_shared<Event>( 2802f3df613SZachary Turner CommandInterpreter::eBroadcastBitResetPrompt, bytes.release()); 2814c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp); 282a8ea5955SJonas Devlieghere } else if (property_path == g_debugger_properties[ePropertyUseColor].name) { 283b9c1b51eSKate Stone // use-color changed. Ping the prompt so it can reset the ansi terminal 284b9c1b51eSKate Stone // codes. 285c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 286b9c1b51eSKate Stone } else if (is_load_script && target_sp && 287b9c1b51eSKate Stone load_script_old_value == eLoadScriptFromSymFileWarn) { 288b9c1b51eSKate Stone if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == 289b9c1b51eSKate Stone eLoadScriptFromSymFileTrue) { 29097206d57SZachary Turner std::list<Status> errors; 2919730339bSEnrico Granata StreamString feedback_stream; 292b9c1b51eSKate Stone if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { 29344d93782SGreg Clayton StreamFileSP stream_sp(GetErrorFile()); 294b9c1b51eSKate Stone if (stream_sp) { 295b9c1b51eSKate Stone for (auto error : errors) { 29644d93782SGreg Clayton stream_sp->Printf("%s\n", error.AsCString()); 29784a53dfbSEnrico Granata } 2989730339bSEnrico Granata if (feedback_stream.GetSize()) 299c156427dSZachary Turner stream_sp->PutCString(feedback_stream.GetString()); 30044d93782SGreg Clayton } 30184a53dfbSEnrico Granata } 30284a53dfbSEnrico Granata } 303b9c1b51eSKate Stone } else if (is_escape_non_printables) { 304ebdc1ac0SEnrico Granata DataVisualization::ForceUpdate(); 305ebdc1ac0SEnrico Granata } 3064c05410fSGreg Clayton } 3074c05410fSGreg Clayton return error; 3084c05410fSGreg Clayton } 3094c05410fSGreg Clayton 310b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const { 31167cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 312b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 313a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 31467cc0636SGreg Clayton } 31567cc0636SGreg Clayton 316b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { 317aff1b357SJason Molenda const uint32_t idx = ePropertyDisassemblyFormat; 318df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 319aff1b357SJason Molenda } 320aff1b357SJason Molenda 321b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const { 32267cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 323df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 32467cc0636SGreg Clayton } 32567cc0636SGreg Clayton 3267f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { 3277f1c1211SPavel Labath const uint32_t idx = ePropertyFrameFormatUnique; 3287f1c1211SPavel Labath return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 3297f1c1211SPavel Labath } 3307f1c1211SPavel Labath 331b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const { 33267cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 333b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 334a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 33567cc0636SGreg Clayton } 33667cc0636SGreg Clayton 337514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const { 33867cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 339b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsString( 340a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_cstr_value); 34167cc0636SGreg Clayton } 34267cc0636SGreg Clayton 343514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) { 34467cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 345df370550SEugene Zelenko m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); 346514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 347b9c1b51eSKate Stone std::string str = 348b9c1b51eSKate Stone lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); 349c3ce7f27SMichael Sartain if (str.length()) 350771ef6d4SMalcolm Parsons new_prompt = str; 35144d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 35267cc0636SGreg Clayton } 35367cc0636SGreg Clayton 3549e046f02SJonas Devlieghere llvm::StringRef Debugger::GetReproducerPath() const { 3559e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 3569e046f02SJonas Devlieghere return r.GetReproducerPath().GetCString(); 3579e046f02SJonas Devlieghere } 3589e046f02SJonas Devlieghere 359b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const { 36067cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 361df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 36267cc0636SGreg Clayton } 36367cc0636SGreg Clayton 3646a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { 3656a9767c7SJim Ingham const uint32_t idx = ePropertyThreadStopFormat; 3666a9767c7SJim Ingham return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 3676a9767c7SJim Ingham } 3686a9767c7SJim Ingham 369b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const { 37067cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 371b9c1b51eSKate Stone return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( 372a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 37367cc0636SGreg Clayton } 37467cc0636SGreg Clayton 375b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { 37667cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 377b9c1b51eSKate Stone return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, 378b9c1b51eSKate Stone script_lang); 37967cc0636SGreg Clayton } 38067cc0636SGreg Clayton 381b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const { 38267cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 383b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 384a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 38567cc0636SGreg Clayton } 38667cc0636SGreg Clayton 387b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) { 38867cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 389df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); 39067cc0636SGreg Clayton } 39167cc0636SGreg Clayton 392b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const { 39367cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 394b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 395a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 39667cc0636SGreg Clayton } 39767cc0636SGreg Clayton 398b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) { 39967cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 400df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 40167cc0636SGreg Clayton } 40267cc0636SGreg Clayton 403b9c1b51eSKate Stone bool Debugger::GetUseColor() const { 404c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 405b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 406a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 407c3ce7f27SMichael Sartain } 408c3ce7f27SMichael Sartain 409b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) { 410c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 411df370550SEugene Zelenko bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 412c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 413c3ce7f27SMichael Sartain return ret; 414c3ce7f27SMichael Sartain } 415c3ce7f27SMichael Sartain 416566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const { 417566afa0aSRaphael Isemann const uint32_t idx = ePropertyHighlightSource; 418566afa0aSRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsBoolean( 419a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 420566afa0aSRaphael Isemann } 421566afa0aSRaphael Isemann 4229666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const { 4239666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumn; 4249666ba75STodd Fiala return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( 425a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4269666ba75STodd Fiala } 4279666ba75STodd Fiala 42820786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const { 4299666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiPrefix; 43020786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4319666ba75STodd Fiala } 4329666ba75STodd Fiala 43320786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const { 4349666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiSuffix; 43520786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4369666ba75STodd Fiala } 4379666ba75STodd Fiala 438b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const { 439b9c1b51eSKate Stone const uint32_t idx = 440b9c1b51eSKate Stone before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 441b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 442a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 44367cc0636SGreg Clayton } 44467cc0636SGreg Clayton 445b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { 44667cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 447b9c1b51eSKate Stone return (Debugger::StopDisassemblyType) 448b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsEnumeration( 449a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 45067cc0636SGreg Clayton } 45167cc0636SGreg Clayton 452b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const { 45367cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 454b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 455a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 45667cc0636SGreg Clayton } 457e372b98dSGreg Clayton 458b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const { 45990a8db30SEnrico Granata const uint32_t idx = ePropertyAutoOneLineSummaries; 460df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 461ebdc1ac0SEnrico Granata } 462553fad5cSEnrico Granata 463b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const { 464ebdc1ac0SEnrico Granata const uint32_t idx = ePropertyEscapeNonPrintables; 465df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 466553fad5cSEnrico Granata } 467553fad5cSEnrico Granata 468b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const { 4696681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 470df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4716681041dSSean Callanan } 4726681041dSSean Callanan 473b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) { 4746681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 475df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4766681041dSSean Callanan } 4776681041dSSean Callanan 478b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const { 4796681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 480df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4816681041dSSean Callanan } 4826681041dSSean Callanan 483b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) { 4846681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 485df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4866681041dSSean Callanan } 4876681041dSSean Callanan 488b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const { 4896681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 490b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 491a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4926681041dSSean Callanan } 4936681041dSSean Callanan 494b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) { 4956681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 496df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); 4976681041dSSean Callanan } 4986681041dSSean Callanan 4991b654882SGreg Clayton #pragma mark Debugger 5001b654882SGreg Clayton 50167cc0636SGreg Clayton // const DebuggerPropertiesSP & 50267cc0636SGreg Clayton // Debugger::GetSettings() const 50367cc0636SGreg Clayton //{ 50467cc0636SGreg Clayton // return m_properties_sp; 50567cc0636SGreg Clayton //} 50667cc0636SGreg Clayton // 50799d0faf2SGreg Clayton 508b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) { 509b9c1b51eSKate Stone assert(g_debugger_list_ptr == nullptr && 510b9c1b51eSKate Stone "Debugger::Initialize called more than once!"); 5116c42e063SGreg Clayton g_debugger_list_mutex_ptr = new std::recursive_mutex(); 5126c42e063SGreg Clayton g_debugger_list_ptr = new DebuggerList(); 5135fb8f797SGreg Clayton g_load_plugin_callback = load_plugin_callback; 51499d0faf2SGreg Clayton } 51530fdc8d8SChris Lattner 516b9c1b51eSKate Stone void Debugger::Terminate() { 517b9c1b51eSKate Stone assert(g_debugger_list_ptr && 518b9c1b51eSKate Stone "Debugger::Terminate called without a matching Debugger::Initialize!"); 519e6e2bb38SZachary Turner 520b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 52199d0faf2SGreg Clayton // Clear our master list of debugger objects 5226c42e063SGreg Clayton { 5236c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 5246c42e063SGreg Clayton for (const auto &debugger : *g_debugger_list_ptr) 525f3cd1819SOleksiy Vyalov debugger->Clear(); 5266c42e063SGreg Clayton g_debugger_list_ptr->clear(); 5276c42e063SGreg Clayton } 5286c42e063SGreg Clayton } 52930fdc8d8SChris Lattner } 53030fdc8d8SChris Lattner 531b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); } 53220bd37f7SCaroline Tice 533b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); } 53420bd37f7SCaroline Tice 53597206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) { 536b9c1b51eSKate Stone if (g_load_plugin_callback) { 537b9c1b51eSKate Stone llvm::sys::DynamicLibrary dynlib = 538b9c1b51eSKate Stone g_load_plugin_callback(shared_from_this(), spec, error); 539b9c1b51eSKate Stone if (dynlib.isValid()) { 54058a559c0SZachary Turner m_loaded_plugins.push_back(dynlib); 54121dfcd9dSEnrico Granata return true; 54221dfcd9dSEnrico Granata } 543b9c1b51eSKate Stone } else { 54405097246SAdrian Prantl // The g_load_plugin_callback is registered in SBDebugger::Initialize() and 54505097246SAdrian Prantl // if the public API layer isn't available (code is linking against all of 54605097246SAdrian Prantl // the internal LLDB static libraries), then we can't load plugins 5475fb8f797SGreg Clayton error.SetErrorString("Public API layer is not available"); 5485fb8f797SGreg Clayton } 54921dfcd9dSEnrico Granata return false; 55021dfcd9dSEnrico Granata } 55121dfcd9dSEnrico Granata 55235e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult 5537d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, 55435e4c84cSJonas Devlieghere llvm::StringRef path) { 55597206d57SZachary Turner Status error; 55621dfcd9dSEnrico Granata 557ad8d48f9SJonas Devlieghere static ConstString g_dylibext(".dylib"); 558ad8d48f9SJonas Devlieghere static ConstString g_solibext(".so"); 55921dfcd9dSEnrico Granata 56021dfcd9dSEnrico Granata if (!baton) 56135e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultQuit; 56221dfcd9dSEnrico Granata 56321dfcd9dSEnrico Granata Debugger *debugger = (Debugger *)baton; 56421dfcd9dSEnrico Granata 5657d86ee5aSZachary Turner namespace fs = llvm::sys::fs; 56605097246SAdrian Prantl // If we have a regular file, a symbolic link or unknown file type, try and 56705097246SAdrian Prantl // process the file. We must handle unknown as sometimes the directory 56821dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 56921dfcd9dSEnrico Granata // file type information. 5707d86ee5aSZachary Turner if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file || 5717d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 5728f3be7a3SJonas Devlieghere FileSpec plugin_file_spec(path); 5738f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(plugin_file_spec); 57421dfcd9dSEnrico Granata 5753cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 576b9c1b51eSKate Stone plugin_file_spec.GetFileNameExtension() != g_solibext) { 57735e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 5783cf443ddSMichael Sartain } 57921dfcd9dSEnrico Granata 58097206d57SZachary Turner Status plugin_load_error; 581e743c782SEnrico Granata debugger->LoadPlugin(plugin_file_spec, plugin_load_error); 58221dfcd9dSEnrico Granata 58335e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 5847d86ee5aSZachary Turner } else if (ft == fs::file_type::directory_file || 5857d86ee5aSZachary Turner ft == fs::file_type::symlink_file || 5867d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 58705097246SAdrian Prantl // Try and recurse into anything that a directory or symbolic link. We must 58805097246SAdrian Prantl // also do this for unknown as sometimes the directory enumeration might be 58905097246SAdrian Prantl // enumerating a file system that doesn't have correct file type 59021dfcd9dSEnrico Granata // information. 59135e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultEnter; 59221dfcd9dSEnrico Granata } 59321dfcd9dSEnrico Granata 59435e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 59521dfcd9dSEnrico Granata } 59621dfcd9dSEnrico Granata 597b9c1b51eSKate Stone void Debugger::InstanceInitialize() { 59821dfcd9dSEnrico Granata const bool find_directories = true; 59921dfcd9dSEnrico Granata const bool find_files = true; 60021dfcd9dSEnrico Granata const bool find_other = true; 60121dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 60260f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) { 603dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 604dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 60535e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 60635e4c84cSJonas Devlieghere find_files, find_other, 60735e4c84cSJonas Devlieghere LoadPluginCallback, this); 60821dfcd9dSEnrico Granata } 60921dfcd9dSEnrico Granata } 61021dfcd9dSEnrico Granata 61160f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) { 612dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 613dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 61435e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 61535e4c84cSJonas Devlieghere find_files, find_other, 61635e4c84cSJonas Devlieghere LoadPluginCallback, this); 61721dfcd9dSEnrico Granata } 61821dfcd9dSEnrico Granata } 619e8cd0c98SGreg Clayton 620e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize(*this); 62121dfcd9dSEnrico Granata } 62221dfcd9dSEnrico Granata 623b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, 624b9c1b51eSKate Stone void *baton) { 625228063cdSJim Ingham DebuggerSP debugger_sp(new Debugger(log_callback, baton)); 626b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6276c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6286c42e063SGreg Clayton g_debugger_list_ptr->push_back(debugger_sp); 6296611103cSGreg Clayton } 63021dfcd9dSEnrico Granata debugger_sp->InstanceInitialize(); 6316611103cSGreg Clayton return debugger_sp; 6326611103cSGreg Clayton } 6336611103cSGreg Clayton 634b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) { 635df370550SEugene Zelenko if (!debugger_sp) 636e02657b1SCaroline Tice return; 637e02657b1SCaroline Tice 6388314c525SJim Ingham debugger_sp->Clear(); 6398314c525SJim Ingham 640b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6416c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6426c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 643b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 644b9c1b51eSKate Stone if ((*pos).get() == debugger_sp.get()) { 6456c42e063SGreg Clayton g_debugger_list_ptr->erase(pos); 646e02657b1SCaroline Tice return; 647e02657b1SCaroline Tice } 648e02657b1SCaroline Tice } 649e02657b1SCaroline Tice } 650c15f55e2SGreg Clayton } 651e02657b1SCaroline Tice 652*e063ecccSJonas Devlieghere DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { 6534d122c40SGreg Clayton DebuggerSP debugger_sp; 654b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6556c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6566c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 657b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 658b9c1b51eSKate Stone if ((*pos)->m_instance_name == instance_name) { 6596920b52bSGreg Clayton debugger_sp = *pos; 6606920b52bSGreg Clayton break; 6616920b52bSGreg Clayton } 6626920b52bSGreg Clayton } 6636920b52bSGreg Clayton } 6643df9a8dfSCaroline Tice return debugger_sp; 6653df9a8dfSCaroline Tice } 6666611103cSGreg Clayton 667b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) { 6684d122c40SGreg Clayton TargetSP target_sp; 669b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6706c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6716c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 672b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 6736611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid); 6746611103cSGreg Clayton if (target_sp) 6756611103cSGreg Clayton break; 6766611103cSGreg Clayton } 677c15f55e2SGreg Clayton } 6786611103cSGreg Clayton return target_sp; 6796611103cSGreg Clayton } 6806611103cSGreg Clayton 681b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) { 682e4e45924SGreg Clayton TargetSP target_sp; 683b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6846c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6856c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 686b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 687e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process); 688e4e45924SGreg Clayton if (target_sp) 689e4e45924SGreg Clayton break; 690e4e45924SGreg Clayton } 691c15f55e2SGreg Clayton } 692e4e45924SGreg Clayton return target_sp; 693e4e45924SGreg Clayton } 694e4e45924SGreg Clayton 695b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) 696b9c1b51eSKate Stone : UserID(g_unique_id++), 6972f3df613SZachary Turner Properties(std::make_shared<OptionValueProperties>()), 6982f3df613SZachary Turner m_input_file_sp(std::make_shared<StreamFile>(stdin, false)), 6992f3df613SZachary Turner m_output_file_sp(std::make_shared<StreamFile>(stdout, false)), 7002f3df613SZachary Turner m_error_file_sp(std::make_shared<StreamFile>(stderr, false)), 701d77c2e09SJonas Devlieghere m_input_recorder(nullptr), 702583bbb1dSJim Ingham m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), 703b9c1b51eSKate Stone m_terminal_state(), m_target_list(*this), m_platform_list(), 704583bbb1dSJim Ingham m_listener_sp(Listener::MakeListener("lldb.Debugger")), 705d5b44036SJonas Devlieghere m_source_manager_up(), m_source_file_cache(), 706f20dd1d5SJonas Devlieghere m_command_interpreter_up( 707f20dd1d5SJonas Devlieghere llvm::make_unique<CommandInterpreter>(*this, false)), 7082b29b432SJonas Devlieghere m_script_interpreter_sp(), m_input_reader_stack(), m_instance_name(), 7092b29b432SJonas Devlieghere m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(), 7104329fe42SGreg Clayton m_sync_broadcaster(nullptr, "lldb.debugger.sync"), 711b9c1b51eSKate Stone m_forward_listener_sp(), m_clear_once() { 71267cc0636SGreg Clayton char instance_cstr[256]; 71367cc0636SGreg Clayton snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 71467cc0636SGreg Clayton m_instance_name.SetCString(instance_cstr); 715228063cdSJim Ingham if (log_callback) 7162f3df613SZachary Turner m_log_callback_stream_sp = 7172f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 718d5b44036SJonas Devlieghere m_command_interpreter_up->Initialize(); 719ded470d3SGreg Clayton // Always add our default platform to the platform list 720615eb7e6SGreg Clayton PlatformSP default_platform_sp(Platform::GetHostPlatform()); 721df370550SEugene Zelenko assert(default_platform_sp); 722ded470d3SGreg Clayton m_platform_list.Append(default_platform_sp, true); 72367cc0636SGreg Clayton 724a8ea5955SJonas Devlieghere m_collection_sp->Initialize(g_debugger_properties); 725b9c1b51eSKate Stone m_collection_sp->AppendProperty( 726b9c1b51eSKate Stone ConstString("target"), 727b9c1b51eSKate Stone ConstString("Settings specify to debugging targets."), true, 72867cc0636SGreg Clayton Target::GetGlobalProperties()->GetValueProperties()); 729b9c1b51eSKate Stone m_collection_sp->AppendProperty( 730b9c1b51eSKate Stone ConstString("platform"), ConstString("Platform settings."), true, 73163acdfdeSOleksiy Vyalov Platform::GetGlobalPlatformProperties()->GetValueProperties()); 732235354beSAdrian Prantl m_collection_sp->AppendProperty( 7333cd29bcfSAdrian Prantl ConstString("symbols"), ConstString("Symbol lookup and cache settings."), 7343cd29bcfSAdrian Prantl true, ModuleList::GetGlobalModuleListProperties().GetValueProperties()); 735d5b44036SJonas Devlieghere if (m_command_interpreter_up) { 736b9c1b51eSKate Stone m_collection_sp->AppendProperty( 737b9c1b51eSKate Stone ConstString("interpreter"), 738754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 739d5b44036SJonas Devlieghere true, m_command_interpreter_up->GetValueProperties()); 740754a9369SGreg Clayton } 741b9c1b51eSKate Stone OptionValueSInt64 *term_width = 742b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64( 743b9c1b51eSKate Stone nullptr, ePropertyTerminalWidth); 74467cc0636SGreg Clayton term_width->SetMinimumValue(10); 74567cc0636SGreg Clayton term_width->SetMaximumValue(1024); 746c3ce7f27SMichael Sartain 747c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 748c3ce7f27SMichael Sartain const char *term = getenv("TERM"); 749c3ce7f27SMichael Sartain if (term && !strcmp(term, "dumb")) 750c3ce7f27SMichael Sartain SetUseColor(false); 751eca9ce14SRaphael Isemann // Turn off use-color if we don't write to a terminal with color support. 752eca9ce14SRaphael Isemann if (!m_output_file_sp->GetFile().GetIsTerminalWithColors()) 753eca9ce14SRaphael Isemann SetUseColor(false); 7548aa23614SDavid Bolvansky 7558aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) 7568aa23614SDavid Bolvansky // Enabling use of ANSI color codes because LLDB is using them to highlight 7578aa23614SDavid Bolvansky // text. 7588aa23614SDavid Bolvansky llvm::sys::Process::UseANSIEscapeCodes(true); 7598aa23614SDavid Bolvansky #endif 76030fdc8d8SChris Lattner } 76130fdc8d8SChris Lattner 762b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); } 7638314c525SJim Ingham 764b9c1b51eSKate Stone void Debugger::Clear() { 76505097246SAdrian Prantl // Make sure we call this function only once. With the C++ global destructor 76605097246SAdrian Prantl // chain having a list of debuggers and with code that can be running on 76705097246SAdrian Prantl // other threads, we need to ensure this doesn't happen multiple times. 7684329fe42SGreg Clayton // 7694329fe42SGreg Clayton // The following functions call Debugger::Clear(): 7704329fe42SGreg Clayton // Debugger::~Debugger(); 7714329fe42SGreg Clayton // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp); 7724329fe42SGreg Clayton // static void Debugger::Terminate(); 773c5f28e2aSKamil Rytarowski llvm::call_once(m_clear_once, [this]() { 77444d93782SGreg Clayton ClearIOHandlers(); 77544d93782SGreg Clayton StopIOHandlerThread(); 77644d93782SGreg Clayton StopEventHandlerThread(); 777583bbb1dSJim Ingham m_listener_sp->Clear(); 7786611103cSGreg Clayton int num_targets = m_target_list.GetNumTargets(); 779b9c1b51eSKate Stone for (int i = 0; i < num_targets; i++) { 780ccbc08e6SGreg Clayton TargetSP target_sp(m_target_list.GetTargetAtIndex(i)); 781b9c1b51eSKate Stone if (target_sp) { 782ccbc08e6SGreg Clayton ProcessSP process_sp(target_sp->GetProcessSP()); 7836611103cSGreg Clayton if (process_sp) 7841fd07059SJim Ingham process_sp->Finalize(); 785ccbc08e6SGreg Clayton target_sp->Destroy(); 7866611103cSGreg Clayton } 78730fdc8d8SChris Lattner } 788583bbb1dSJim Ingham m_broadcaster_manager_sp->Clear(); 78930fdc8d8SChris Lattner 790b9c1b51eSKate Stone // Close the input file _before_ we close the input read communications 79105097246SAdrian Prantl // class as it does NOT own the input file, our m_input_file does. 792c5917d9aSJim Ingham m_terminal_state.Clear(); 79344d93782SGreg Clayton if (m_input_file_sp) 79444d93782SGreg Clayton m_input_file_sp->GetFile().Close(); 7950c4129f2SGreg Clayton 796d5b44036SJonas Devlieghere m_command_interpreter_up->Clear(); 7974329fe42SGreg Clayton }); 7988314c525SJim Ingham } 79930fdc8d8SChris Lattner 800b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const { 80144d93782SGreg Clayton // return m_input_comm.GetCloseOnEOF(); 80244d93782SGreg Clayton return false; 803fc3f027dSGreg Clayton } 804fc3f027dSGreg Clayton 805b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) { 80644d93782SGreg Clayton // m_input_comm.SetCloseOnEOF(b); 807fc3f027dSGreg Clayton } 808fc3f027dSGreg Clayton 809b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() { 810d5b44036SJonas Devlieghere return !m_command_interpreter_up->GetSynchronous(); 81130fdc8d8SChris Lattner } 81230fdc8d8SChris Lattner 813b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) { 814d5b44036SJonas Devlieghere m_command_interpreter_up->SetSynchronous(!async_execution); 81530fdc8d8SChris Lattner } 81630fdc8d8SChris Lattner 817d77c2e09SJonas Devlieghere repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; } 818d77c2e09SJonas Devlieghere 819d77c2e09SJonas Devlieghere void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership, 820d77c2e09SJonas Devlieghere repro::DataRecorder *recorder) { 821d77c2e09SJonas Devlieghere m_input_recorder = recorder; 82244d93782SGreg Clayton if (m_input_file_sp) 82344d93782SGreg Clayton m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership); 82444d93782SGreg Clayton else 8252f3df613SZachary Turner m_input_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership); 82644d93782SGreg Clayton 82744d93782SGreg Clayton File &in_file = m_input_file_sp->GetFile(); 828df370550SEugene Zelenko if (!in_file.IsValid()) 82951b1e2d2SGreg Clayton in_file.SetStream(stdin, true); 83030fdc8d8SChris Lattner 83105097246SAdrian Prantl // Save away the terminal state if that is relevant, so that we can restore 83205097246SAdrian Prantl // it in RestoreInputState. 833c5917d9aSJim Ingham SaveInputTerminalState(); 83430fdc8d8SChris Lattner } 83530fdc8d8SChris Lattner 836b9c1b51eSKate Stone void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) { 83744d93782SGreg Clayton if (m_output_file_sp) 83844d93782SGreg Clayton m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership); 83944d93782SGreg Clayton else 8402f3df613SZachary Turner m_output_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership); 84144d93782SGreg Clayton 84244d93782SGreg Clayton File &out_file = m_output_file_sp->GetFile(); 843df370550SEugene Zelenko if (!out_file.IsValid()) 84451b1e2d2SGreg Clayton out_file.SetStream(stdout, false); 8452f88aadfSCaroline Tice 8462b29b432SJonas Devlieghere // Do not create the ScriptInterpreter just for setting the output file 8472b29b432SJonas Devlieghere // handle as the constructor will know how to do the right thing on its own. 8482b29b432SJonas Devlieghere if (ScriptInterpreter *script_interpreter = 8492b29b432SJonas Devlieghere GetScriptInterpreter(/*can_create=*/false)) 850b588726eSEnrico Granata script_interpreter->ResetOutputFileHandle(fh); 85130fdc8d8SChris Lattner } 85230fdc8d8SChris Lattner 853b9c1b51eSKate Stone void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) { 85444d93782SGreg Clayton if (m_error_file_sp) 85544d93782SGreg Clayton m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership); 85644d93782SGreg Clayton else 8572f3df613SZachary Turner m_error_file_sp = std::make_shared<StreamFile>(fh, tranfer_ownership); 85844d93782SGreg Clayton 85944d93782SGreg Clayton File &err_file = m_error_file_sp->GetFile(); 860df370550SEugene Zelenko if (!err_file.IsValid()) 86151b1e2d2SGreg Clayton err_file.SetStream(stderr, false); 86230fdc8d8SChris Lattner } 86330fdc8d8SChris Lattner 864b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() { 865b9c1b51eSKate Stone if (m_input_file_sp) { 86644d93782SGreg Clayton File &in_file = m_input_file_sp->GetFile(); 867c5917d9aSJim Ingham if (in_file.GetDescriptor() != File::kInvalidDescriptor) 868c5917d9aSJim Ingham m_terminal_state.Save(in_file.GetDescriptor(), true); 869c5917d9aSJim Ingham } 87044d93782SGreg Clayton } 871c5917d9aSJim Ingham 872b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } 873c5917d9aSJim Ingham 874b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() { 87530fdc8d8SChris Lattner ExecutionContext exe_ctx; 876c14ee32dSGreg Clayton TargetSP target_sp(GetSelectedTarget()); 877c14ee32dSGreg Clayton exe_ctx.SetTargetSP(target_sp); 87830fdc8d8SChris Lattner 879b9c1b51eSKate Stone if (target_sp) { 880c14ee32dSGreg Clayton ProcessSP process_sp(target_sp->GetProcessSP()); 881c14ee32dSGreg Clayton exe_ctx.SetProcessSP(process_sp); 882b9c1b51eSKate Stone if (process_sp && !process_sp->IsRunning()) { 883c14ee32dSGreg Clayton ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread()); 884b9c1b51eSKate Stone if (thread_sp) { 885c14ee32dSGreg Clayton exe_ctx.SetThreadSP(thread_sp); 886c14ee32dSGreg Clayton exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame()); 887df370550SEugene Zelenko if (exe_ctx.GetFramePtr() == nullptr) 888c14ee32dSGreg Clayton exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0)); 88930fdc8d8SChris Lattner } 89030fdc8d8SChris Lattner } 89130fdc8d8SChris Lattner } 89230fdc8d8SChris Lattner return exe_ctx; 89330fdc8d8SChris Lattner } 89430fdc8d8SChris Lattner 895b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() { 89616ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 89744d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 898efed6131SCaroline Tice if (reader_sp) 89944d93782SGreg Clayton reader_sp->Interrupt(); 900efed6131SCaroline Tice } 901efed6131SCaroline Tice 902b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() { 90316ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 90444d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 905efed6131SCaroline Tice if (reader_sp) 90644d93782SGreg Clayton reader_sp->GotEOF(); 907efed6131SCaroline Tice } 908efed6131SCaroline Tice 909b9c1b51eSKate Stone void Debugger::ClearIOHandlers() { 910b9c1b51eSKate Stone // The bottom input reader should be the main debugger input reader. We do 911b9c1b51eSKate Stone // not want to close that one here. 91216ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 913b9c1b51eSKate Stone while (m_input_reader_stack.GetSize() > 1) { 91444d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 9153d6086f6SCaroline Tice if (reader_sp) 9164446487dSPavel Labath PopIOHandler(reader_sp); 9173d6086f6SCaroline Tice } 9183d6086f6SCaroline Tice } 9193d6086f6SCaroline Tice 920b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() { 921b9c1b51eSKate Stone while (true) { 92244d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 92330fdc8d8SChris Lattner if (!reader_sp) 92430fdc8d8SChris Lattner break; 92530fdc8d8SChris Lattner 92644d93782SGreg Clayton reader_sp->Run(); 92744d93782SGreg Clayton 92844d93782SGreg Clayton // Remove all input readers that are done from the top of the stack 929b9c1b51eSKate Stone while (true) { 93044d93782SGreg Clayton IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); 93144d93782SGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 9324446487dSPavel Labath PopIOHandler(top_reader_sp); 93330fdc8d8SChris Lattner else 93430fdc8d8SChris Lattner break; 93530fdc8d8SChris Lattner } 93630fdc8d8SChris Lattner } 93744d93782SGreg Clayton ClearIOHandlers(); 93844d93782SGreg Clayton } 93930fdc8d8SChris Lattner 940b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) { 94144d93782SGreg Clayton return m_input_reader_stack.IsTop(reader_sp); 94244d93782SGreg Clayton } 94330fdc8d8SChris Lattner 944b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, 945b9c1b51eSKate Stone IOHandler::Type second_top_type) { 9466681041dSSean Callanan return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type); 9476681041dSSean Callanan } 9486681041dSSean Callanan 949b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { 9504446487dSPavel Labath lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile(); 9514446487dSPavel Labath m_input_reader_stack.PrintAsync(stream.get(), s, len); 9524446487dSPavel Labath } 95344d93782SGreg Clayton 954b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { 95544d93782SGreg Clayton return m_input_reader_stack.GetTopIOHandlerControlSequence(ch); 95630fdc8d8SChris Lattner } 95730fdc8d8SChris Lattner 958b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() { 959a487aa4cSKate Stone return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); 960a487aa4cSKate Stone } 961a487aa4cSKate Stone 962b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() { 963a487aa4cSKate Stone return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); 964a487aa4cSKate Stone } 965a487aa4cSKate Stone 966b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) { 96744d93782SGreg Clayton PushIOHandler(reader_sp); 968577508dfSGreg Clayton 969577508dfSGreg Clayton IOHandlerSP top_reader_sp = reader_sp; 970b9c1b51eSKate Stone while (top_reader_sp) { 971577508dfSGreg Clayton top_reader_sp->Run(); 972577508dfSGreg Clayton 973b9c1b51eSKate Stone if (top_reader_sp.get() == reader_sp.get()) { 974577508dfSGreg Clayton if (PopIOHandler(reader_sp)) 975577508dfSGreg Clayton break; 976577508dfSGreg Clayton } 977577508dfSGreg Clayton 978b9c1b51eSKate Stone while (true) { 979577508dfSGreg Clayton top_reader_sp = m_input_reader_stack.Top(); 980577508dfSGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 9814446487dSPavel Labath PopIOHandler(top_reader_sp); 982577508dfSGreg Clayton else 983577508dfSGreg Clayton break; 984577508dfSGreg Clayton } 985577508dfSGreg Clayton } 98644d93782SGreg Clayton } 98744d93782SGreg Clayton 988b9c1b51eSKate Stone void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in, 989b9c1b51eSKate Stone StreamFileSP &out, 990b9c1b51eSKate Stone StreamFileSP &err) { 99105097246SAdrian Prantl // Before an IOHandler runs, it must have in/out/err streams. This function 99205097246SAdrian Prantl // is called when one ore more of the streams are nullptr. We use the top 99305097246SAdrian Prantl // input reader's in/out/err streams, or fall back to the debugger file 99405097246SAdrian Prantl // handles, or we fall back onto stdin/stdout/stderr as a last resort. 99544d93782SGreg Clayton 99616ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 99744d93782SGreg Clayton IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); 99844d93782SGreg Clayton // If no STDIN has been set, then set it appropriately 999b9c1b51eSKate Stone if (!in) { 100044d93782SGreg Clayton if (top_reader_sp) 100144d93782SGreg Clayton in = top_reader_sp->GetInputStreamFile(); 100244d93782SGreg Clayton else 100344d93782SGreg Clayton in = GetInputFile(); 100444d93782SGreg Clayton 100544d93782SGreg Clayton // If there is nothing, use stdin 100644d93782SGreg Clayton if (!in) 10072f3df613SZachary Turner in = std::make_shared<StreamFile>(stdin, false); 100844d93782SGreg Clayton } 100944d93782SGreg Clayton // If no STDOUT has been set, then set it appropriately 1010b9c1b51eSKate Stone if (!out) { 101144d93782SGreg Clayton if (top_reader_sp) 101244d93782SGreg Clayton out = top_reader_sp->GetOutputStreamFile(); 101344d93782SGreg Clayton else 101444d93782SGreg Clayton out = GetOutputFile(); 101544d93782SGreg Clayton 101644d93782SGreg Clayton // If there is nothing, use stdout 101744d93782SGreg Clayton if (!out) 10182f3df613SZachary Turner out = std::make_shared<StreamFile>(stdout, false); 101944d93782SGreg Clayton } 102044d93782SGreg Clayton // If no STDERR has been set, then set it appropriately 1021b9c1b51eSKate Stone if (!err) { 102244d93782SGreg Clayton if (top_reader_sp) 102344d93782SGreg Clayton err = top_reader_sp->GetErrorStreamFile(); 102444d93782SGreg Clayton else 102544d93782SGreg Clayton err = GetErrorFile(); 102644d93782SGreg Clayton 102744d93782SGreg Clayton // If there is nothing, use stderr 102844d93782SGreg Clayton if (!err) 10292f3df613SZachary Turner err = std::make_shared<StreamFile>(stdout, false); 103044d93782SGreg Clayton } 103144d93782SGreg Clayton } 103244d93782SGreg Clayton 1033c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp, 1034c01783a8SRaphael Isemann bool cancel_top_handler) { 103530fdc8d8SChris Lattner if (!reader_sp) 103630fdc8d8SChris Lattner return; 1037b44880caSCaroline Tice 103816ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 10394446487dSPavel Labath 10404446487dSPavel Labath // Get the current top input reader... 104144d93782SGreg Clayton IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); 1042b44880caSCaroline Tice 1043b4874f1aSGreg Clayton // Don't push the same IO handler twice... 10444446487dSPavel Labath if (reader_sp == top_reader_sp) 10454446487dSPavel Labath return; 10464446487dSPavel Labath 104744d93782SGreg Clayton // Push our new input reader 1048d5a0a01bSCaroline Tice m_input_reader_stack.Push(reader_sp); 10494446487dSPavel Labath reader_sp->Activate(); 105044d93782SGreg Clayton 105105097246SAdrian Prantl // Interrupt the top input reader to it will exit its Run() function and let 105205097246SAdrian Prantl // this new input reader take over 1053b9c1b51eSKate Stone if (top_reader_sp) { 105444d93782SGreg Clayton top_reader_sp->Deactivate(); 1055c01783a8SRaphael Isemann if (cancel_top_handler) 10564446487dSPavel Labath top_reader_sp->Cancel(); 105730fdc8d8SChris Lattner } 1058b4874f1aSGreg Clayton } 105930fdc8d8SChris Lattner 1060b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) { 10614446487dSPavel Labath if (!pop_reader_sp) 10624446487dSPavel Labath return false; 106330fdc8d8SChris Lattner 106416ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 106544d93782SGreg Clayton 106605097246SAdrian Prantl // The reader on the stop of the stack is done, so let the next read on the 106705097246SAdrian Prantl // stack refresh its prompt and if there is one... 10684446487dSPavel Labath if (m_input_reader_stack.IsEmpty()) 10694446487dSPavel Labath return false; 10704446487dSPavel Labath 107144d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 107230fdc8d8SChris Lattner 10734446487dSPavel Labath if (pop_reader_sp != reader_sp) 10744446487dSPavel Labath return false; 10754446487dSPavel Labath 107644d93782SGreg Clayton reader_sp->Deactivate(); 1077b4874f1aSGreg Clayton reader_sp->Cancel(); 1078d5a0a01bSCaroline Tice m_input_reader_stack.Pop(); 107930fdc8d8SChris Lattner 1080d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 108130fdc8d8SChris Lattner if (reader_sp) 108244d93782SGreg Clayton reader_sp->Activate(); 108344d93782SGreg Clayton 108444d93782SGreg Clayton return true; 108530fdc8d8SChris Lattner } 10866611103cSGreg Clayton 1087b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() { 10882f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, true); 10895b52f0c7SJim Ingham } 10905b52f0c7SJim Ingham 1091b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() { 10922f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, false); 10935b52f0c7SJim Ingham } 10945b52f0c7SJim Ingham 1095b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() { 1096b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 10976c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 10986c42e063SGreg Clayton return g_debugger_list_ptr->size(); 1099061858ceSEnrico Granata } 1100c15f55e2SGreg Clayton return 0; 1101c15f55e2SGreg Clayton } 1102061858ceSEnrico Granata 1103b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) { 1104061858ceSEnrico Granata DebuggerSP debugger_sp; 1105061858ceSEnrico Granata 1106b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 11076c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 11086c42e063SGreg Clayton if (index < g_debugger_list_ptr->size()) 11096c42e063SGreg Clayton debugger_sp = g_debugger_list_ptr->at(index); 1110c15f55e2SGreg Clayton } 1111061858ceSEnrico Granata 1112061858ceSEnrico Granata return debugger_sp; 1113061858ceSEnrico Granata } 1114061858ceSEnrico Granata 1115b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) { 11164d122c40SGreg Clayton DebuggerSP debugger_sp; 1117ebc1bb27SCaroline Tice 1118b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 11196c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 11206c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 1121b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 1122b9c1b51eSKate Stone if ((*pos)->GetID() == id) { 1123ebc1bb27SCaroline Tice debugger_sp = *pos; 1124ebc1bb27SCaroline Tice break; 1125ebc1bb27SCaroline Tice } 1126ebc1bb27SCaroline Tice } 1127c15f55e2SGreg Clayton } 1128ebc1bb27SCaroline Tice return debugger_sp; 1129ebc1bb27SCaroline Tice } 11303df9a8dfSCaroline Tice 1131b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, 1132aff1b357SJason Molenda const SymbolContext *sc, 1133aff1b357SJason Molenda const SymbolContext *prev_sc, 1134aff1b357SJason Molenda const ExecutionContext *exe_ctx, 1135b9c1b51eSKate Stone const Address *addr, Stream &s) { 1136554f68d3SGreg Clayton FormatEntity::Entry format_entry; 1137554f68d3SGreg Clayton 1138b9c1b51eSKate Stone if (format == nullptr) { 1139df370550SEugene Zelenko if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) 1140aff1b357SJason Molenda format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1141b9c1b51eSKate Stone if (format == nullptr) { 1142554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format_entry); 1143554f68d3SGreg Clayton format = &format_entry; 1144554f68d3SGreg Clayton } 1145aff1b357SJason Molenda } 1146aff1b357SJason Molenda bool function_changed = false; 1147aff1b357SJason Molenda bool initial_function = false; 1148b9c1b51eSKate Stone if (prev_sc && (prev_sc->function || prev_sc->symbol)) { 1149b9c1b51eSKate Stone if (sc && (sc->function || sc->symbol)) { 1150b9c1b51eSKate Stone if (prev_sc->symbol && sc->symbol) { 1151b9c1b51eSKate Stone if (!sc->symbol->Compare(prev_sc->symbol->GetName(), 1152b9c1b51eSKate Stone prev_sc->symbol->GetType())) { 1153aff1b357SJason Molenda function_changed = true; 1154aff1b357SJason Molenda } 1155b9c1b51eSKate Stone } else if (prev_sc->function && sc->function) { 1156b9c1b51eSKate Stone if (prev_sc->function->GetMangled() != sc->function->GetMangled()) { 1157aff1b357SJason Molenda function_changed = true; 1158aff1b357SJason Molenda } 1159aff1b357SJason Molenda } 1160aff1b357SJason Molenda } 1161aff1b357SJason Molenda } 116205097246SAdrian Prantl // The first context on a list of instructions will have a prev_sc that has 116305097246SAdrian Prantl // no Function or Symbol -- if SymbolContext had an IsValid() method, it 1164aff1b357SJason Molenda // would return false. But we do get a prev_sc pointer. 1165b9c1b51eSKate Stone if ((sc && (sc->function || sc->symbol)) && prev_sc && 1166b9c1b51eSKate Stone (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) { 1167aff1b357SJason Molenda initial_function = true; 1168aff1b357SJason Molenda } 1169b9c1b51eSKate Stone return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, 1170b9c1b51eSKate Stone function_changed, initial_function); 1171aff1b357SJason Molenda } 1172aff1b357SJason Molenda 1173b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, 1174b9c1b51eSKate Stone void *baton) { 11754f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 11764f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 11774f02b22dSJim Ingham // callback. 11782f3df613SZachary Turner m_log_callback_stream_sp = 11792f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 1180228063cdSJim Ingham } 1181228063cdSJim Ingham 11825e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel, 11835e336903SPavel Labath llvm::ArrayRef<const char *> categories, 11845e336903SPavel Labath llvm::StringRef log_file, uint32_t log_options, 1185775588c0SPavel Labath llvm::raw_ostream &error_stream) { 11865fae71c5SPavel Labath const bool should_close = true; 11875fae71c5SPavel Labath const bool unbuffered = true; 11885fae71c5SPavel Labath 11895fae71c5SPavel Labath std::shared_ptr<llvm::raw_ostream> log_stream_sp; 1190b9c1b51eSKate Stone if (m_log_callback_stream_sp) { 1191228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 1192228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 1193b9c1b51eSKate Stone log_options |= 1194b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 11955e336903SPavel Labath } else if (log_file.empty()) { 11965fae71c5SPavel Labath log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( 11975fae71c5SPavel Labath GetOutputFile()->GetFile().GetDescriptor(), !should_close, unbuffered); 1198b9c1b51eSKate Stone } else { 11995fae71c5SPavel Labath auto pos = m_log_streams.find(log_file); 1200c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 1201c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 1202b9c1b51eSKate Stone if (!log_stream_sp) { 12035fae71c5SPavel Labath llvm::sys::fs::OpenFlags flags = llvm::sys::fs::F_Text; 12045fae71c5SPavel Labath if (log_options & LLDB_LOG_OPTION_APPEND) 12055fae71c5SPavel Labath flags |= llvm::sys::fs::F_Append; 12065fae71c5SPavel Labath int FD; 12071f67a3cbSZachary Turner if (std::error_code ec = llvm::sys::fs::openFileForWrite( 12081f67a3cbSZachary Turner log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) { 1209775588c0SPavel Labath error_stream << "Unable to open log file: " << ec.message(); 12105fae71c5SPavel Labath return false; 12115fae71c5SPavel Labath } 12122f3df613SZachary Turner log_stream_sp = 12132f3df613SZachary Turner std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered); 1214228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 1215228063cdSJim Ingham } 1216228063cdSJim Ingham } 1217df370550SEugene Zelenko assert(log_stream_sp); 1218228063cdSJim Ingham 1219228063cdSJim Ingham if (log_options == 0) 1220b9c1b51eSKate Stone log_options = 1221b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 1222228063cdSJim Ingham 1223b9c1b51eSKate Stone return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories, 1224b9c1b51eSKate Stone error_stream); 1225228063cdSJim Ingham } 1226228063cdSJim Ingham 12272b29b432SJonas Devlieghere ScriptInterpreter *Debugger::GetScriptInterpreter(bool can_create) { 12282b29b432SJonas Devlieghere std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex); 12292b29b432SJonas Devlieghere 12302b29b432SJonas Devlieghere if (!m_script_interpreter_sp) { 12312b29b432SJonas Devlieghere if (!can_create) 12322b29b432SJonas Devlieghere return nullptr; 12332b29b432SJonas Devlieghere m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage( 12342b29b432SJonas Devlieghere GetScriptLanguage(), *this); 12352b29b432SJonas Devlieghere } 12362b29b432SJonas Devlieghere 12372b29b432SJonas Devlieghere return m_script_interpreter_sp.get(); 12382b29b432SJonas Devlieghere } 12392b29b432SJonas Devlieghere 1240b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() { 1241d5b44036SJonas Devlieghere if (!m_source_manager_up) 1242d5b44036SJonas Devlieghere m_source_manager_up = llvm::make_unique<SourceManager>(shared_from_this()); 1243d5b44036SJonas Devlieghere return *m_source_manager_up; 12449585fbfcSGreg Clayton } 12459585fbfcSGreg Clayton 124644d93782SGreg Clayton // This function handles events that were broadcast by the process. 1247b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) { 124844d93782SGreg Clayton using namespace lldb; 1249b9c1b51eSKate Stone const uint32_t event_type = 1250b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 1251b9c1b51eSKate Stone event_sp); 125244d93782SGreg Clayton 125344d93782SGreg Clayton // if (event_type & eBreakpointEventTypeAdded 125444d93782SGreg Clayton // || event_type & eBreakpointEventTypeRemoved 125544d93782SGreg Clayton // || event_type & eBreakpointEventTypeEnabled 125644d93782SGreg Clayton // || event_type & eBreakpointEventTypeDisabled 125744d93782SGreg Clayton // || event_type & eBreakpointEventTypeCommandChanged 125844d93782SGreg Clayton // || event_type & eBreakpointEventTypeConditionChanged 125944d93782SGreg Clayton // || event_type & eBreakpointEventTypeIgnoreChanged 126044d93782SGreg Clayton // || event_type & eBreakpointEventTypeLocationsResolved) 126144d93782SGreg Clayton // { 1262b9c1b51eSKate Stone // // Don't do anything about these events, since the breakpoint 1263b9c1b51eSKate Stone // commands already echo these actions. 126444d93782SGreg Clayton // } 126544d93782SGreg Clayton // 1266b9c1b51eSKate Stone if (event_type & eBreakpointEventTypeLocationsAdded) { 1267b9c1b51eSKate Stone uint32_t num_new_locations = 1268b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 1269b9c1b51eSKate Stone event_sp); 1270b9c1b51eSKate Stone if (num_new_locations > 0) { 1271b9c1b51eSKate Stone BreakpointSP breakpoint = 1272b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 12734446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1274b9c1b51eSKate Stone if (output_sp) { 127544d93782SGreg Clayton output_sp->Printf("%d location%s added to breakpoint %d\n", 1276b9c1b51eSKate Stone num_new_locations, num_new_locations == 1 ? "" : "s", 127744d93782SGreg Clayton breakpoint->GetID()); 12784446487dSPavel Labath output_sp->Flush(); 127944d93782SGreg Clayton } 128044d93782SGreg Clayton } 128144d93782SGreg Clayton } 128244d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsRemoved) 128344d93782SGreg Clayton // { 1284b9c1b51eSKate Stone // // These locations just get disabled, not sure it is worth spamming 1285b9c1b51eSKate Stone // folks about this on the command line. 128644d93782SGreg Clayton // } 128744d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsResolved) 128844d93782SGreg Clayton // { 1289b9c1b51eSKate Stone // // This might be an interesting thing to note, but I'm going to 1290b9c1b51eSKate Stone // leave it quiet for now, it just looked noisy. 129144d93782SGreg Clayton // } 129244d93782SGreg Clayton } 129344d93782SGreg Clayton 1294a9d58436SPavel Labath void Debugger::FlushProcessOutput(Process &process, bool flush_stdout, 1295a9d58436SPavel Labath bool flush_stderr) { 1296a9d58436SPavel Labath const auto &flush = [&](Stream &stream, 1297a9d58436SPavel Labath size_t (Process::*get)(char *, size_t, Status &)) { 129897206d57SZachary Turner Status error; 129944d93782SGreg Clayton size_t len; 1300a9d58436SPavel Labath char buffer[1024]; 1301a9d58436SPavel Labath while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0) 1302a9d58436SPavel Labath stream.Write(buffer, len); 1303a9d58436SPavel Labath stream.Flush(); 1304a9d58436SPavel Labath }; 130544d93782SGreg Clayton 1306a9d58436SPavel Labath std::lock_guard<std::mutex> guard(m_output_flush_mutex); 1307a9d58436SPavel Labath if (flush_stdout) 1308a9d58436SPavel Labath flush(*GetAsyncOutputStream(), &Process::GetSTDOUT); 1309a9d58436SPavel Labath if (flush_stderr) 1310a9d58436SPavel Labath flush(*GetAsyncErrorStream(), &Process::GetSTDERR); 131144d93782SGreg Clayton } 131244d93782SGreg Clayton 131344d93782SGreg Clayton // This function handles events that were broadcast by the process. 1314b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) { 131544d93782SGreg Clayton using namespace lldb; 131644d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 1317b9c1b51eSKate Stone ProcessSP process_sp = 1318b9c1b51eSKate Stone (event_type == Process::eBroadcastBitStructuredData) 131975930019STodd Fiala ? EventDataStructuredData::GetProcessFromEvent(event_sp.get()) 132075930019STodd Fiala : Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 132144d93782SGreg Clayton 13224446487dSPavel Labath StreamSP output_stream_sp = GetAsyncOutputStream(); 13234446487dSPavel Labath StreamSP error_stream_sp = GetAsyncErrorStream(); 132444d93782SGreg Clayton const bool gui_enabled = IsForwardingEvents(); 132544d93782SGreg Clayton 1326b9c1b51eSKate Stone if (!gui_enabled) { 1327b4874f1aSGreg Clayton bool pop_process_io_handler = false; 132844d93782SGreg Clayton assert(process_sp); 132944d93782SGreg Clayton 13304446487dSPavel Labath bool state_is_stopped = false; 1331b9c1b51eSKate Stone const bool got_state_changed = 1332b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStateChanged) != 0; 13334446487dSPavel Labath const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0; 13344446487dSPavel Labath const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0; 1335b9c1b51eSKate Stone const bool got_structured_data = 1336b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStructuredData) != 0; 133775930019STodd Fiala 1338b9c1b51eSKate Stone if (got_state_changed) { 1339b9c1b51eSKate Stone StateType event_state = 1340b9c1b51eSKate Stone Process::ProcessEventData::GetStateFromEvent(event_sp.get()); 13414446487dSPavel Labath state_is_stopped = StateIsStoppedState(event_state, false); 134244d93782SGreg Clayton } 1343b4874f1aSGreg Clayton 13444446487dSPavel Labath // Display running state changes first before any STDIO 1345b9c1b51eSKate Stone if (got_state_changed && !state_is_stopped) { 1346b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1347b9c1b51eSKate Stone pop_process_io_handler); 134844d93782SGreg Clayton } 1349b4874f1aSGreg Clayton 1350a9d58436SPavel Labath // Now display STDOUT and STDERR 1351a9d58436SPavel Labath FlushProcessOutput(*process_sp, got_stdout || got_state_changed, 1352a9d58436SPavel Labath got_stderr || got_state_changed); 1353b4874f1aSGreg Clayton 135475930019STodd Fiala // Give structured data events an opportunity to display. 1355b9c1b51eSKate Stone if (got_structured_data) { 135675930019STodd Fiala StructuredDataPluginSP plugin_sp = 135775930019STodd Fiala EventDataStructuredData::GetPluginFromEvent(event_sp.get()); 1358b9c1b51eSKate Stone if (plugin_sp) { 135975930019STodd Fiala auto structured_data_sp = 136075930019STodd Fiala EventDataStructuredData::GetObjectFromEvent(event_sp.get()); 1361b9c1b51eSKate Stone if (output_stream_sp) { 136275930019STodd Fiala StreamString content_stream; 136397206d57SZachary Turner Status error = 1364b9c1b51eSKate Stone plugin_sp->GetDescription(structured_data_sp, content_stream); 1365b9c1b51eSKate Stone if (error.Success()) { 1366b9c1b51eSKate Stone if (!content_stream.GetString().empty()) { 136775930019STodd Fiala // Add newline. 136875930019STodd Fiala content_stream.PutChar('\n'); 136975930019STodd Fiala content_stream.Flush(); 137075930019STodd Fiala 137175930019STodd Fiala // Print it. 1372771ef6d4SMalcolm Parsons output_stream_sp->PutCString(content_stream.GetString()); 137375930019STodd Fiala } 1374b9c1b51eSKate Stone } else { 137575930019STodd Fiala error_stream_sp->Printf("Failed to print structured " 137675930019STodd Fiala "data with plugin %s: %s", 1377b9c1b51eSKate Stone plugin_sp->GetPluginName().AsCString(), 137875930019STodd Fiala error.AsCString()); 137975930019STodd Fiala } 138075930019STodd Fiala } 138175930019STodd Fiala } 138275930019STodd Fiala } 138375930019STodd Fiala 13844446487dSPavel Labath // Now display any stopped state changes after any STDIO 1385b9c1b51eSKate Stone if (got_state_changed && state_is_stopped) { 1386b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1387b9c1b51eSKate Stone pop_process_io_handler); 138844d93782SGreg Clayton } 138944d93782SGreg Clayton 13904446487dSPavel Labath output_stream_sp->Flush(); 13914446487dSPavel Labath error_stream_sp->Flush(); 139244d93782SGreg Clayton 1393b4874f1aSGreg Clayton if (pop_process_io_handler) 1394b4874f1aSGreg Clayton process_sp->PopProcessIOHandler(); 1395b4874f1aSGreg Clayton } 1396b4874f1aSGreg Clayton } 1397b4874f1aSGreg Clayton 1398b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) { 139905097246SAdrian Prantl // At present the only thread event we handle is the Frame Changed event, and 140005097246SAdrian Prantl // all we do for that is just reprint the thread status for that thread. 140144d93782SGreg Clayton using namespace lldb; 140244d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 14036a9767c7SJim Ingham const bool stop_format = true; 140444d93782SGreg Clayton if (event_type == Thread::eBroadcastBitStackChanged || 1405b9c1b51eSKate Stone event_type == Thread::eBroadcastBitThreadSelected) { 1406b9c1b51eSKate Stone ThreadSP thread_sp( 1407b9c1b51eSKate Stone Thread::ThreadEventData::GetThreadFromEvent(event_sp.get())); 1408b9c1b51eSKate Stone if (thread_sp) { 14096a9767c7SJim Ingham thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format); 141044d93782SGreg Clayton } 141144d93782SGreg Clayton } 141244d93782SGreg Clayton } 141344d93782SGreg Clayton 1414b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; } 141544d93782SGreg Clayton 1416b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) { 141744d93782SGreg Clayton m_forward_listener_sp = listener_sp; 141844d93782SGreg Clayton } 141944d93782SGreg Clayton 1420b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) { 142144d93782SGreg Clayton m_forward_listener_sp.reset(); 142244d93782SGreg Clayton } 142344d93782SGreg Clayton 1424b9c1b51eSKate Stone void Debugger::DefaultEventHandler() { 1425583bbb1dSJim Ingham ListenerSP listener_sp(GetListener()); 142644d93782SGreg Clayton ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 142744d93782SGreg Clayton ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 142844d93782SGreg Clayton ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 142944d93782SGreg Clayton BroadcastEventSpec target_event_spec(broadcaster_class_target, 143044d93782SGreg Clayton Target::eBroadcastBitBreakpointChanged); 143144d93782SGreg Clayton 1432b9c1b51eSKate Stone BroadcastEventSpec process_event_spec( 1433b9c1b51eSKate Stone broadcaster_class_process, 1434b9c1b51eSKate Stone Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT | 1435b9c1b51eSKate Stone Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData); 143644d93782SGreg Clayton 143744d93782SGreg Clayton BroadcastEventSpec thread_event_spec(broadcaster_class_thread, 143844d93782SGreg Clayton Thread::eBroadcastBitStackChanged | 143944d93782SGreg Clayton Thread::eBroadcastBitThreadSelected); 144044d93782SGreg Clayton 1441b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1442b9c1b51eSKate Stone target_event_spec); 1443b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1444b9c1b51eSKate Stone process_event_spec); 1445b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1446b9c1b51eSKate Stone thread_event_spec); 1447b9c1b51eSKate Stone listener_sp->StartListeningForEvents( 1448d5b44036SJonas Devlieghere m_command_interpreter_up.get(), 144944d93782SGreg Clayton CommandInterpreter::eBroadcastBitQuitCommandReceived | 145044d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousOutputData | 145144d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousErrorData); 145244d93782SGreg Clayton 145305097246SAdrian Prantl // Let the thread that spawned us know that we have started up and that we 145405097246SAdrian Prantl // are now listening to all required events so no events get missed 1455afa91e33SGreg Clayton m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); 1456afa91e33SGreg Clayton 145744d93782SGreg Clayton bool done = false; 1458b9c1b51eSKate Stone while (!done) { 145944d93782SGreg Clayton EventSP event_sp; 1460d35031e1SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 1461b9c1b51eSKate Stone if (event_sp) { 146244d93782SGreg Clayton Broadcaster *broadcaster = event_sp->GetBroadcaster(); 1463b9c1b51eSKate Stone if (broadcaster) { 146444d93782SGreg Clayton uint32_t event_type = event_sp->GetType(); 146544d93782SGreg Clayton ConstString broadcaster_class(broadcaster->GetBroadcasterClass()); 1466b9c1b51eSKate Stone if (broadcaster_class == broadcaster_class_process) { 146744d93782SGreg Clayton HandleProcessEvent(event_sp); 1468b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_target) { 1469b9c1b51eSKate Stone if (Breakpoint::BreakpointEventData::GetEventDataFromEvent( 1470b9c1b51eSKate Stone event_sp.get())) { 147144d93782SGreg Clayton HandleBreakpointEvent(event_sp); 147244d93782SGreg Clayton } 1473b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_thread) { 147444d93782SGreg Clayton HandleThreadEvent(event_sp); 1475d5b44036SJonas Devlieghere } else if (broadcaster == m_command_interpreter_up.get()) { 1476b9c1b51eSKate Stone if (event_type & 1477b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived) { 147844d93782SGreg Clayton done = true; 1479b9c1b51eSKate Stone } else if (event_type & 1480b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitAsynchronousErrorData) { 1481b9c1b51eSKate Stone const char *data = reinterpret_cast<const char *>( 1482b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1483b9c1b51eSKate Stone if (data && data[0]) { 14844446487dSPavel Labath StreamSP error_sp(GetAsyncErrorStream()); 1485b9c1b51eSKate Stone if (error_sp) { 148644d93782SGreg Clayton error_sp->PutCString(data); 148744d93782SGreg Clayton error_sp->Flush(); 148844d93782SGreg Clayton } 148944d93782SGreg Clayton } 1490b9c1b51eSKate Stone } else if (event_type & CommandInterpreter:: 1491b9c1b51eSKate Stone eBroadcastBitAsynchronousOutputData) { 1492b9c1b51eSKate Stone const char *data = reinterpret_cast<const char *>( 1493b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1494b9c1b51eSKate Stone if (data && data[0]) { 14954446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1496b9c1b51eSKate Stone if (output_sp) { 149744d93782SGreg Clayton output_sp->PutCString(data); 149844d93782SGreg Clayton output_sp->Flush(); 149944d93782SGreg Clayton } 150044d93782SGreg Clayton } 150144d93782SGreg Clayton } 150244d93782SGreg Clayton } 150344d93782SGreg Clayton } 150444d93782SGreg Clayton 150544d93782SGreg Clayton if (m_forward_listener_sp) 150644d93782SGreg Clayton m_forward_listener_sp->AddEvent(event_sp); 150744d93782SGreg Clayton } 150844d93782SGreg Clayton } 150944d93782SGreg Clayton } 151044d93782SGreg Clayton } 151144d93782SGreg Clayton 1512b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) { 151344d93782SGreg Clayton ((Debugger *)arg)->DefaultEventHandler(); 151485200645SKonrad Kleine return {}; 151544d93782SGreg Clayton } 151644d93782SGreg Clayton 1517b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() { 1518b9c1b51eSKate Stone if (!m_event_handler_thread.IsJoinable()) { 151905097246SAdrian Prantl // We must synchronize with the DefaultEventHandler() thread to ensure it 152005097246SAdrian Prantl // is up and running and listening to events before we return from this 152105097246SAdrian Prantl // function. We do this by listening to events for the 1522afa91e33SGreg Clayton // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster 15231a728f66STatyana Krasnukha ConstString full_name("lldb.debugger.event-handler"); 15241a728f66STatyana Krasnukha ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString())); 1525b9c1b51eSKate Stone listener_sp->StartListeningForEvents(&m_sync_broadcaster, 1526b9c1b51eSKate Stone eBroadcastBitEventThreadIsListening); 1527afa91e33SGreg Clayton 15281a728f66STatyana Krasnukha auto thread_name = 1529*e063ecccSJonas Devlieghere full_name.GetLength() < llvm::get_max_thread_name_length() 1530*e063ecccSJonas Devlieghere ? full_name.AsCString() 1531*e063ecccSJonas Devlieghere : "dbg.evt-handler"; 15321a728f66STatyana Krasnukha 15337c2896a2SZachary Turner // Use larger 8MB stack for this thread 1534f39c2e18SJonas Devlieghere llvm::Expected<HostThread> event_handler_thread = 1535f39c2e18SJonas Devlieghere ThreadLauncher::LaunchThread(thread_name, EventHandlerThread, this, 1536f39c2e18SJonas Devlieghere g_debugger_event_thread_stack_bytes); 1537f39c2e18SJonas Devlieghere 1538f39c2e18SJonas Devlieghere if (event_handler_thread) { 1539f39c2e18SJonas Devlieghere m_event_handler_thread = *event_handler_thread; 1540f39c2e18SJonas Devlieghere } else { 1541f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 1542f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 1543f39c2e18SJonas Devlieghere llvm::toString(event_handler_thread.takeError())); 1544f39c2e18SJonas Devlieghere } 1545afa91e33SGreg Clayton 154605097246SAdrian Prantl // Make sure DefaultEventHandler() is running and listening to events 154705097246SAdrian Prantl // before we return from this function. We are only listening for events of 154805097246SAdrian Prantl // type eBroadcastBitEventThreadIsListening so we don't need to check the 154905097246SAdrian Prantl // event, we just need to wait an infinite amount of time for it (nullptr 155005097246SAdrian Prantl // timeout as the first parameter) 1551afa91e33SGreg Clayton lldb::EventSP event_sp; 1552d35031e1SPavel Labath listener_sp->GetEvent(event_sp, llvm::None); 1553807b6b32SGreg Clayton } 1554acee96aeSZachary Turner return m_event_handler_thread.IsJoinable(); 155544d93782SGreg Clayton } 155644d93782SGreg Clayton 1557b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() { 1558b9c1b51eSKate Stone if (m_event_handler_thread.IsJoinable()) { 1559b9c1b51eSKate Stone GetCommandInterpreter().BroadcastEvent( 1560b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived); 156139de3110SZachary Turner m_event_handler_thread.Join(nullptr); 156244d93782SGreg Clayton } 156344d93782SGreg Clayton } 156444d93782SGreg Clayton 1565b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) { 156644d93782SGreg Clayton Debugger *debugger = (Debugger *)arg; 15679aaab558SSiva Chandra debugger->ExecuteIOHandlers(); 156844d93782SGreg Clayton debugger->StopEventHandlerThread(); 156985200645SKonrad Kleine return {}; 157044d93782SGreg Clayton } 157144d93782SGreg Clayton 1572b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } 15736681041dSSean Callanan 1574b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() { 1575f39c2e18SJonas Devlieghere if (!m_io_handler_thread.IsJoinable()) { 1576f39c2e18SJonas Devlieghere llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread( 1577f39c2e18SJonas Devlieghere "lldb.debugger.io-handler", IOHandlerThread, this, 1578807b6b32SGreg Clayton 8 * 1024 * 1024); // Use larger 8MB stack for this thread 1579f39c2e18SJonas Devlieghere if (io_handler_thread) { 1580f39c2e18SJonas Devlieghere m_io_handler_thread = *io_handler_thread; 1581f39c2e18SJonas Devlieghere } else { 1582f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 1583f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 1584f39c2e18SJonas Devlieghere llvm::toString(io_handler_thread.takeError())); 1585f39c2e18SJonas Devlieghere } 1586f39c2e18SJonas Devlieghere } 1587acee96aeSZachary Turner return m_io_handler_thread.IsJoinable(); 158844d93782SGreg Clayton } 158944d93782SGreg Clayton 1590b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() { 1591b9c1b51eSKate Stone if (m_io_handler_thread.IsJoinable()) { 159244d93782SGreg Clayton if (m_input_file_sp) 159344d93782SGreg Clayton m_input_file_sp->GetFile().Close(); 159439de3110SZachary Turner m_io_handler_thread.Join(nullptr); 159544d93782SGreg Clayton } 159644d93782SGreg Clayton } 159744d93782SGreg Clayton 1598b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() { 1599b9c1b51eSKate Stone if (HasIOHandlerThread()) { 16006681041dSSean Callanan thread_result_t result; 16016681041dSSean Callanan m_io_handler_thread.Join(&result); 16026681041dSSean Callanan m_io_handler_thread = LLDB_INVALID_HOST_THREAD; 16036681041dSSean Callanan } 16046681041dSSean Callanan } 16056681041dSSean Callanan 1606b9c1b51eSKate Stone Target *Debugger::GetDummyTarget() { 1607893c932aSJim Ingham return m_target_list.GetDummyTarget(*this).get(); 1608893c932aSJim Ingham } 1609893c932aSJim Ingham 1610b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { 161133df7cd3SJim Ingham Target *target = nullptr; 1612b9c1b51eSKate Stone if (!prefer_dummy) { 161333df7cd3SJim Ingham target = m_target_list.GetSelectedTarget().get(); 161433df7cd3SJim Ingham if (target) 161533df7cd3SJim Ingham return target; 161633df7cd3SJim Ingham } 1617893c932aSJim Ingham 1618893c932aSJim Ingham return GetDummyTarget(); 1619893c932aSJim Ingham } 162044d93782SGreg Clayton 162197206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) { 162297206d57SZachary Turner Status err; 16233e7e915dSSean Callanan FileSpec repl_executable; 16243e7e915dSSean Callanan 1625b9c1b51eSKate Stone if (language == eLanguageTypeUnknown) { 162697f84e87SSean Callanan std::set<LanguageType> repl_languages; 162797f84e87SSean Callanan 162897f84e87SSean Callanan Language::GetLanguagesSupportingREPLs(repl_languages); 162997f84e87SSean Callanan 1630b9c1b51eSKate Stone if (repl_languages.size() == 1) { 163197f84e87SSean Callanan language = *repl_languages.begin(); 1632b9c1b51eSKate Stone } else if (repl_languages.empty()) { 1633b9c1b51eSKate Stone err.SetErrorStringWithFormat( 1634b9c1b51eSKate Stone "LLDB isn't configured with REPL support for any languages."); 163597f84e87SSean Callanan return err; 1636b9c1b51eSKate Stone } else { 1637b9c1b51eSKate Stone err.SetErrorStringWithFormat( 1638b9c1b51eSKate Stone "Multiple possible REPL languages. Please specify a language."); 163997f84e87SSean Callanan return err; 164097f84e87SSean Callanan } 164197f84e87SSean Callanan } 164297f84e87SSean Callanan 1643b9c1b51eSKate Stone Target *const target = 1644b9c1b51eSKate Stone nullptr; // passing in an empty target means the REPL must create one 16453e7e915dSSean Callanan 16463b682de6SSean Callanan REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); 16473e7e915dSSean Callanan 1648b9c1b51eSKate Stone if (!err.Success()) { 16493e7e915dSSean Callanan return err; 16503e7e915dSSean Callanan } 16513e7e915dSSean Callanan 1652b9c1b51eSKate Stone if (!repl_sp) { 1653b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't find a REPL for %s", 1654b9c1b51eSKate Stone Language::GetNameForLanguageType(language)); 16553e7e915dSSean Callanan return err; 16563e7e915dSSean Callanan } 16573e7e915dSSean Callanan 16583e7e915dSSean Callanan repl_sp->SetCompilerOptions(repl_options); 16593e7e915dSSean Callanan repl_sp->RunLoop(); 16603e7e915dSSean Callanan 16613e7e915dSSean Callanan return err; 16623e7e915dSSean Callanan } 1663