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[] = { 96e063ecccSJonas Devlieghere { 97e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNever, 98e063ecccSJonas Devlieghere "never", 99e063ecccSJonas Devlieghere "Never show disassembly when displaying a stop context.", 100e063ecccSJonas Devlieghere }, 101e063ecccSJonas Devlieghere { 102e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoDebugInfo, 103e063ecccSJonas Devlieghere "no-debuginfo", 104e063ecccSJonas Devlieghere "Show disassembly when there is no debug information.", 105e063ecccSJonas Devlieghere }, 106e063ecccSJonas Devlieghere { 107e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoSource, 108e063ecccSJonas Devlieghere "no-source", 109e063ecccSJonas Devlieghere "Show disassembly when there is no source information, or the source " 110e063ecccSJonas Devlieghere "file " 111e063ecccSJonas Devlieghere "is missing when displaying a stop context.", 112e063ecccSJonas Devlieghere }, 113e063ecccSJonas Devlieghere { 114e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeAlways, 115e063ecccSJonas Devlieghere "always", 116e063ecccSJonas Devlieghere "Always show disassembly when displaying a stop context.", 117e063ecccSJonas Devlieghere }, 118e063ecccSJonas Devlieghere }; 119e372b98dSGreg Clayton 1208fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = { 121e063ecccSJonas Devlieghere { 122e063ecccSJonas Devlieghere eScriptLanguageNone, 123e063ecccSJonas Devlieghere "none", 124e063ecccSJonas Devlieghere "Disable scripting languages.", 125e063ecccSJonas Devlieghere }, 126e063ecccSJonas Devlieghere { 127e063ecccSJonas Devlieghere eScriptLanguagePython, 128e063ecccSJonas Devlieghere "python", 129e063ecccSJonas Devlieghere "Select python as the default scripting language.", 130e063ecccSJonas Devlieghere }, 131e063ecccSJonas Devlieghere { 132e063ecccSJonas Devlieghere eScriptLanguageDefault, 133e063ecccSJonas Devlieghere "default", 134e063ecccSJonas Devlieghere "Select the lldb default as the default scripting language.", 135e063ecccSJonas Devlieghere }, 136e063ecccSJonas 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[] = { 217e063ecccSJonas Devlieghere { 218e063ecccSJonas Devlieghere eStopShowColumnAnsiOrCaret, 219e063ecccSJonas Devlieghere "ansi-or-caret", 220e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when color/ANSI " 221e063ecccSJonas Devlieghere "mode is enabled; otherwise, fall back to using a text-only caret (^) " 222e063ecccSJonas Devlieghere "as if \"caret-only\" mode was selected.", 223e063ecccSJonas Devlieghere }, 224e063ecccSJonas Devlieghere { 225e063ecccSJonas Devlieghere eStopShowColumnAnsi, 226e063ecccSJonas Devlieghere "ansi", 227e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when running LLDB " 228e063ecccSJonas Devlieghere "with color/ANSI enabled.", 229e063ecccSJonas Devlieghere }, 230e063ecccSJonas Devlieghere { 231e063ecccSJonas Devlieghere eStopShowColumnCaret, 232e063ecccSJonas Devlieghere "caret", 233e063ecccSJonas Devlieghere "Highlight the stop column with a caret character (^) underneath the " 234e063ecccSJonas Devlieghere "stop column. This method introduces a new line in source listings " 235e063ecccSJonas Devlieghere "that display thread stop locations.", 236e063ecccSJonas Devlieghere }, 237e063ecccSJonas Devlieghere { 238e063ecccSJonas Devlieghere eStopShowColumnNone, 239e063ecccSJonas Devlieghere "none", 240e063ecccSJonas Devlieghere "Do not highlight the stop column.", 241e063ecccSJonas Devlieghere }, 242e063ecccSJonas 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) { 258e063ecccSJonas Devlieghere bool is_load_script = 259e063ecccSJonas Devlieghere (property_path == "target.load-script-from-symbol-file"); 260e5814d78SRaphael Isemann // These properties might change how we visualize data. 261e5814d78SRaphael Isemann bool invalidate_data_vis = (property_path == "escape-non-printables"); 262e5814d78SRaphael Isemann invalidate_data_vis |= 263e5814d78SRaphael Isemann (property_path == "target.max-zero-padding-in-float-format"); 264e5814d78SRaphael Isemann if (invalidate_data_vis) { 265e5814d78SRaphael Isemann DataVisualization::ForceUpdate(); 266e5814d78SRaphael Isemann } 267e5814d78SRaphael Isemann 26884a53dfbSEnrico Granata TargetSP target_sp; 269397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 270b9c1b51eSKate Stone if (is_load_script && exe_ctx->GetTargetSP()) { 27184a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 272b9c1b51eSKate Stone load_script_old_value = 273b9c1b51eSKate Stone target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 27484a53dfbSEnrico Granata } 27597206d57SZachary Turner Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value)); 276b9c1b51eSKate Stone if (error.Success()) { 27784a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 278a8ea5955SJonas Devlieghere if (property_path == g_debugger_properties[ePropertyPrompt].name) { 279514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 2804b3c0fd5SJonas Devlieghere std::string str = lldb_private::ansi::FormatAnsiTerminalCodes( 281b9c1b51eSKate Stone new_prompt, GetUseColor()); 282c3ce7f27SMichael Sartain if (str.length()) 283771ef6d4SMalcolm Parsons new_prompt = str; 28444d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 285a8f3ae7cSJonas Devlieghere auto bytes = std::make_unique<EventDataBytes>(new_prompt); 2862f3df613SZachary Turner auto prompt_change_event_sp = std::make_shared<Event>( 2872f3df613SZachary Turner CommandInterpreter::eBroadcastBitResetPrompt, bytes.release()); 2884c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp); 289a8ea5955SJonas Devlieghere } else if (property_path == g_debugger_properties[ePropertyUseColor].name) { 290b9c1b51eSKate Stone // use-color changed. Ping the prompt so it can reset the ansi terminal 291b9c1b51eSKate Stone // codes. 292c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 293b9c1b51eSKate Stone } else if (is_load_script && target_sp && 294b9c1b51eSKate Stone load_script_old_value == eLoadScriptFromSymFileWarn) { 295b9c1b51eSKate Stone if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == 296b9c1b51eSKate Stone eLoadScriptFromSymFileTrue) { 29797206d57SZachary Turner std::list<Status> errors; 2989730339bSEnrico Granata StreamString feedback_stream; 299b9c1b51eSKate Stone if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { 3007ca15ba7SLawrence D'Anna Stream &s = GetErrorStream(); 301b9c1b51eSKate Stone for (auto error : errors) { 3027ca15ba7SLawrence D'Anna s.Printf("%s\n", error.AsCString()); 30384a53dfbSEnrico Granata } 3049730339bSEnrico Granata if (feedback_stream.GetSize()) 3057ca15ba7SLawrence D'Anna s.PutCString(feedback_stream.GetString()); 30684a53dfbSEnrico Granata } 30784a53dfbSEnrico Granata } 308ebdc1ac0SEnrico Granata } 3094c05410fSGreg Clayton } 3104c05410fSGreg Clayton return error; 3114c05410fSGreg Clayton } 3124c05410fSGreg Clayton 313b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const { 31467cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 315b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 316a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 31767cc0636SGreg Clayton } 31867cc0636SGreg Clayton 319b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { 320aff1b357SJason Molenda const uint32_t idx = ePropertyDisassemblyFormat; 321df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 322aff1b357SJason Molenda } 323aff1b357SJason Molenda 324b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const { 32567cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 326df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 32767cc0636SGreg Clayton } 32867cc0636SGreg Clayton 3297f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { 3307f1c1211SPavel Labath const uint32_t idx = ePropertyFrameFormatUnique; 3317f1c1211SPavel Labath return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 3327f1c1211SPavel Labath } 3337f1c1211SPavel Labath 334b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const { 33567cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 336b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 337a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 33867cc0636SGreg Clayton } 33967cc0636SGreg Clayton 340514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const { 34167cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 342b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsString( 343a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_cstr_value); 34467cc0636SGreg Clayton } 34567cc0636SGreg Clayton 346514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) { 34767cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 348df370550SEugene Zelenko m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); 349514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 350b9c1b51eSKate Stone std::string str = 3514b3c0fd5SJonas Devlieghere lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); 352c3ce7f27SMichael Sartain if (str.length()) 353771ef6d4SMalcolm Parsons new_prompt = str; 35444d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 35567cc0636SGreg Clayton } 35667cc0636SGreg Clayton 3579e046f02SJonas Devlieghere llvm::StringRef Debugger::GetReproducerPath() const { 3589e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 3599e046f02SJonas Devlieghere return r.GetReproducerPath().GetCString(); 3609e046f02SJonas Devlieghere } 3619e046f02SJonas Devlieghere 362b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const { 36367cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 364df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 36567cc0636SGreg Clayton } 36667cc0636SGreg Clayton 3676a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { 3686a9767c7SJim Ingham const uint32_t idx = ePropertyThreadStopFormat; 3696a9767c7SJim Ingham return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 3706a9767c7SJim Ingham } 3716a9767c7SJim Ingham 372b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const { 37367cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 374b9c1b51eSKate Stone return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( 375a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 37667cc0636SGreg Clayton } 37767cc0636SGreg Clayton 378b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { 37967cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 380b9c1b51eSKate Stone return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, 381b9c1b51eSKate Stone script_lang); 38267cc0636SGreg Clayton } 38367cc0636SGreg Clayton 384b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const { 38567cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 386b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 387a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 38867cc0636SGreg Clayton } 38967cc0636SGreg Clayton 390b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) { 39167cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 392df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); 39367cc0636SGreg Clayton } 39467cc0636SGreg Clayton 395b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const { 39667cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 397b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 398a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 39967cc0636SGreg Clayton } 40067cc0636SGreg Clayton 401b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) { 40267cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 403df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 40467cc0636SGreg Clayton } 40567cc0636SGreg Clayton 406b9c1b51eSKate Stone bool Debugger::GetUseColor() const { 407c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 408b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 409a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 410c3ce7f27SMichael Sartain } 411c3ce7f27SMichael Sartain 412b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) { 413c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 414df370550SEugene Zelenko bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 415c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 416c3ce7f27SMichael Sartain return ret; 417c3ce7f27SMichael Sartain } 418c3ce7f27SMichael Sartain 419566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const { 420566afa0aSRaphael Isemann const uint32_t idx = ePropertyHighlightSource; 421566afa0aSRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsBoolean( 422a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 423566afa0aSRaphael Isemann } 424566afa0aSRaphael Isemann 4259666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const { 4269666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumn; 4279666ba75STodd Fiala return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( 428a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4299666ba75STodd Fiala } 4309666ba75STodd Fiala 43120786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const { 4329666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiPrefix; 43320786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4349666ba75STodd Fiala } 4359666ba75STodd Fiala 43620786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const { 4379666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiSuffix; 43820786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4399666ba75STodd Fiala } 4409666ba75STodd Fiala 441b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const { 442b9c1b51eSKate Stone const uint32_t idx = 443b9c1b51eSKate Stone before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 444b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 445a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 44667cc0636SGreg Clayton } 44767cc0636SGreg Clayton 448b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { 44967cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 450b9c1b51eSKate Stone return (Debugger::StopDisassemblyType) 451b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsEnumeration( 452a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 45367cc0636SGreg Clayton } 45467cc0636SGreg Clayton 455b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const { 45667cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 457b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 458a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 45967cc0636SGreg Clayton } 460e372b98dSGreg Clayton 461b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const { 46290a8db30SEnrico Granata const uint32_t idx = ePropertyAutoOneLineSummaries; 463df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 464ebdc1ac0SEnrico Granata } 465553fad5cSEnrico Granata 466b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const { 467ebdc1ac0SEnrico Granata const uint32_t idx = ePropertyEscapeNonPrintables; 468df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 469553fad5cSEnrico Granata } 470553fad5cSEnrico Granata 471b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const { 4726681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 473df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4746681041dSSean Callanan } 4756681041dSSean Callanan 476b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) { 4776681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 478df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4796681041dSSean Callanan } 4806681041dSSean Callanan 481b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const { 4826681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 483df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4846681041dSSean Callanan } 4856681041dSSean Callanan 486b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) { 4876681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 488df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4896681041dSSean Callanan } 4906681041dSSean Callanan 491b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const { 4926681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 493b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 494a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4956681041dSSean Callanan } 4966681041dSSean Callanan 497b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) { 4986681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 499df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); 5006681041dSSean Callanan } 5016681041dSSean Callanan 5021b654882SGreg Clayton #pragma mark Debugger 5031b654882SGreg Clayton 50467cc0636SGreg Clayton // const DebuggerPropertiesSP & 50567cc0636SGreg Clayton // Debugger::GetSettings() const 50667cc0636SGreg Clayton //{ 50767cc0636SGreg Clayton // return m_properties_sp; 50867cc0636SGreg Clayton //} 50967cc0636SGreg Clayton // 51099d0faf2SGreg Clayton 511b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) { 512b9c1b51eSKate Stone assert(g_debugger_list_ptr == nullptr && 513b9c1b51eSKate Stone "Debugger::Initialize called more than once!"); 5146c42e063SGreg Clayton g_debugger_list_mutex_ptr = new std::recursive_mutex(); 5156c42e063SGreg Clayton g_debugger_list_ptr = new DebuggerList(); 5165fb8f797SGreg Clayton g_load_plugin_callback = load_plugin_callback; 51799d0faf2SGreg Clayton } 51830fdc8d8SChris Lattner 519b9c1b51eSKate Stone void Debugger::Terminate() { 520b9c1b51eSKate Stone assert(g_debugger_list_ptr && 521b9c1b51eSKate Stone "Debugger::Terminate called without a matching Debugger::Initialize!"); 522e6e2bb38SZachary Turner 523b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 52499d0faf2SGreg Clayton // Clear our master list of debugger objects 5256c42e063SGreg Clayton { 5266c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 5276c42e063SGreg Clayton for (const auto &debugger : *g_debugger_list_ptr) 528f3cd1819SOleksiy Vyalov debugger->Clear(); 5296c42e063SGreg Clayton g_debugger_list_ptr->clear(); 5306c42e063SGreg Clayton } 5316c42e063SGreg Clayton } 53230fdc8d8SChris Lattner } 53330fdc8d8SChris Lattner 534b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); } 53520bd37f7SCaroline Tice 536b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); } 53720bd37f7SCaroline Tice 53897206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) { 539b9c1b51eSKate Stone if (g_load_plugin_callback) { 540b9c1b51eSKate Stone llvm::sys::DynamicLibrary dynlib = 541b9c1b51eSKate Stone g_load_plugin_callback(shared_from_this(), spec, error); 542b9c1b51eSKate Stone if (dynlib.isValid()) { 54358a559c0SZachary Turner m_loaded_plugins.push_back(dynlib); 54421dfcd9dSEnrico Granata return true; 54521dfcd9dSEnrico Granata } 546b9c1b51eSKate Stone } else { 54705097246SAdrian Prantl // The g_load_plugin_callback is registered in SBDebugger::Initialize() and 54805097246SAdrian Prantl // if the public API layer isn't available (code is linking against all of 54905097246SAdrian Prantl // the internal LLDB static libraries), then we can't load plugins 5505fb8f797SGreg Clayton error.SetErrorString("Public API layer is not available"); 5515fb8f797SGreg Clayton } 55221dfcd9dSEnrico Granata return false; 55321dfcd9dSEnrico Granata } 55421dfcd9dSEnrico Granata 55535e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult 5567d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, 55735e4c84cSJonas Devlieghere llvm::StringRef path) { 55897206d57SZachary Turner Status error; 55921dfcd9dSEnrico Granata 560ad8d48f9SJonas Devlieghere static ConstString g_dylibext(".dylib"); 561ad8d48f9SJonas Devlieghere static ConstString g_solibext(".so"); 56221dfcd9dSEnrico Granata 56321dfcd9dSEnrico Granata if (!baton) 56435e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultQuit; 56521dfcd9dSEnrico Granata 56621dfcd9dSEnrico Granata Debugger *debugger = (Debugger *)baton; 56721dfcd9dSEnrico Granata 5687d86ee5aSZachary Turner namespace fs = llvm::sys::fs; 56905097246SAdrian Prantl // If we have a regular file, a symbolic link or unknown file type, try and 57005097246SAdrian Prantl // process the file. We must handle unknown as sometimes the directory 57121dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 57221dfcd9dSEnrico Granata // file type information. 5737d86ee5aSZachary Turner if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file || 5747d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 5758f3be7a3SJonas Devlieghere FileSpec plugin_file_spec(path); 5768f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(plugin_file_spec); 57721dfcd9dSEnrico Granata 5783cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 579b9c1b51eSKate Stone plugin_file_spec.GetFileNameExtension() != g_solibext) { 58035e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 5813cf443ddSMichael Sartain } 58221dfcd9dSEnrico Granata 58397206d57SZachary Turner Status plugin_load_error; 584e743c782SEnrico Granata debugger->LoadPlugin(plugin_file_spec, plugin_load_error); 58521dfcd9dSEnrico Granata 58635e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 5877d86ee5aSZachary Turner } else if (ft == fs::file_type::directory_file || 5887d86ee5aSZachary Turner ft == fs::file_type::symlink_file || 5897d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 59005097246SAdrian Prantl // Try and recurse into anything that a directory or symbolic link. We must 59105097246SAdrian Prantl // also do this for unknown as sometimes the directory enumeration might be 59205097246SAdrian Prantl // enumerating a file system that doesn't have correct file type 59321dfcd9dSEnrico Granata // information. 59435e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultEnter; 59521dfcd9dSEnrico Granata } 59621dfcd9dSEnrico Granata 59735e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 59821dfcd9dSEnrico Granata } 59921dfcd9dSEnrico Granata 600b9c1b51eSKate Stone void Debugger::InstanceInitialize() { 60121dfcd9dSEnrico Granata const bool find_directories = true; 60221dfcd9dSEnrico Granata const bool find_files = true; 60321dfcd9dSEnrico Granata const bool find_other = true; 60421dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 60560f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) { 606dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 607dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 60835e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 60935e4c84cSJonas Devlieghere find_files, find_other, 61035e4c84cSJonas Devlieghere LoadPluginCallback, this); 61121dfcd9dSEnrico Granata } 61221dfcd9dSEnrico Granata } 61321dfcd9dSEnrico Granata 61460f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) { 615dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 616dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 61735e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 61835e4c84cSJonas Devlieghere find_files, find_other, 61935e4c84cSJonas Devlieghere LoadPluginCallback, this); 62021dfcd9dSEnrico Granata } 62121dfcd9dSEnrico Granata } 622e8cd0c98SGreg Clayton 623e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize(*this); 62421dfcd9dSEnrico Granata } 62521dfcd9dSEnrico Granata 626b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, 627b9c1b51eSKate Stone void *baton) { 628228063cdSJim Ingham DebuggerSP debugger_sp(new Debugger(log_callback, baton)); 629b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6306c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6316c42e063SGreg Clayton g_debugger_list_ptr->push_back(debugger_sp); 6326611103cSGreg Clayton } 63321dfcd9dSEnrico Granata debugger_sp->InstanceInitialize(); 6346611103cSGreg Clayton return debugger_sp; 6356611103cSGreg Clayton } 6366611103cSGreg Clayton 637b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) { 638df370550SEugene Zelenko if (!debugger_sp) 639e02657b1SCaroline Tice return; 640e02657b1SCaroline Tice 6418314c525SJim Ingham debugger_sp->Clear(); 6428314c525SJim Ingham 643b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6446c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6456c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 646b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 647b9c1b51eSKate Stone if ((*pos).get() == debugger_sp.get()) { 6486c42e063SGreg Clayton g_debugger_list_ptr->erase(pos); 649e02657b1SCaroline Tice return; 650e02657b1SCaroline Tice } 651e02657b1SCaroline Tice } 652e02657b1SCaroline Tice } 653c15f55e2SGreg Clayton } 654e02657b1SCaroline Tice 655e063ecccSJonas Devlieghere DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { 6564d122c40SGreg Clayton DebuggerSP debugger_sp; 657b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6586c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6596c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 660b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 661b9c1b51eSKate Stone if ((*pos)->m_instance_name == instance_name) { 6626920b52bSGreg Clayton debugger_sp = *pos; 6636920b52bSGreg Clayton break; 6646920b52bSGreg Clayton } 6656920b52bSGreg Clayton } 6666920b52bSGreg Clayton } 6673df9a8dfSCaroline Tice return debugger_sp; 6683df9a8dfSCaroline Tice } 6696611103cSGreg Clayton 670b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) { 6714d122c40SGreg Clayton TargetSP target_sp; 672b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6736c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6746c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 675b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 6766611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid); 6776611103cSGreg Clayton if (target_sp) 6786611103cSGreg Clayton break; 6796611103cSGreg Clayton } 680c15f55e2SGreg Clayton } 6816611103cSGreg Clayton return target_sp; 6826611103cSGreg Clayton } 6836611103cSGreg Clayton 684b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) { 685e4e45924SGreg Clayton TargetSP target_sp; 686b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6876c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6886c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 689b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 690e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process); 691e4e45924SGreg Clayton if (target_sp) 692e4e45924SGreg Clayton break; 693e4e45924SGreg Clayton } 694c15f55e2SGreg Clayton } 695e4e45924SGreg Clayton return target_sp; 696e4e45924SGreg Clayton } 697e4e45924SGreg Clayton 698b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) 699b9c1b51eSKate Stone : UserID(g_unique_id++), 7002f3df613SZachary Turner Properties(std::make_shared<OptionValueProperties>()), 701f913fd6eSLawrence D'Anna m_input_file_sp(std::make_shared<NativeFile>(stdin, false)), 7027ca15ba7SLawrence D'Anna m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)), 7037ca15ba7SLawrence D'Anna m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)), 704d77c2e09SJonas Devlieghere m_input_recorder(nullptr), 705583bbb1dSJim Ingham m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), 706b9c1b51eSKate Stone m_terminal_state(), m_target_list(*this), m_platform_list(), 707583bbb1dSJim Ingham m_listener_sp(Listener::MakeListener("lldb.Debugger")), 708d5b44036SJonas Devlieghere m_source_manager_up(), m_source_file_cache(), 709f20dd1d5SJonas Devlieghere m_command_interpreter_up( 710a8f3ae7cSJonas Devlieghere std::make_unique<CommandInterpreter>(*this, false)), 711*bbf70c04SJonas Devlieghere m_input_reader_stack(), m_instance_name(), m_loaded_plugins(), 712*bbf70c04SJonas Devlieghere m_event_handler_thread(), m_io_handler_thread(), 7134329fe42SGreg Clayton m_sync_broadcaster(nullptr, "lldb.debugger.sync"), 714b9c1b51eSKate Stone m_forward_listener_sp(), m_clear_once() { 71567cc0636SGreg Clayton char instance_cstr[256]; 71667cc0636SGreg Clayton snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); 71767cc0636SGreg Clayton m_instance_name.SetCString(instance_cstr); 718228063cdSJim Ingham if (log_callback) 7192f3df613SZachary Turner m_log_callback_stream_sp = 7202f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 721d5b44036SJonas Devlieghere m_command_interpreter_up->Initialize(); 722ded470d3SGreg Clayton // Always add our default platform to the platform list 723615eb7e6SGreg Clayton PlatformSP default_platform_sp(Platform::GetHostPlatform()); 724df370550SEugene Zelenko assert(default_platform_sp); 725ded470d3SGreg Clayton m_platform_list.Append(default_platform_sp, true); 72667cc0636SGreg Clayton 727d43d912bSRaphael Isemann m_dummy_target_sp = m_target_list.GetDummyTarget(*this); 728d43d912bSRaphael Isemann assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?"); 729d43d912bSRaphael Isemann 730a8ea5955SJonas Devlieghere m_collection_sp->Initialize(g_debugger_properties); 731b9c1b51eSKate Stone m_collection_sp->AppendProperty( 732b9c1b51eSKate Stone ConstString("target"), 733b9c1b51eSKate Stone ConstString("Settings specify to debugging targets."), true, 73467cc0636SGreg Clayton Target::GetGlobalProperties()->GetValueProperties()); 735b9c1b51eSKate Stone m_collection_sp->AppendProperty( 736b9c1b51eSKate Stone ConstString("platform"), ConstString("Platform settings."), true, 73763acdfdeSOleksiy Vyalov Platform::GetGlobalPlatformProperties()->GetValueProperties()); 738235354beSAdrian Prantl m_collection_sp->AppendProperty( 7393cd29bcfSAdrian Prantl ConstString("symbols"), ConstString("Symbol lookup and cache settings."), 7403cd29bcfSAdrian Prantl true, ModuleList::GetGlobalModuleListProperties().GetValueProperties()); 741d5b44036SJonas Devlieghere if (m_command_interpreter_up) { 742b9c1b51eSKate Stone m_collection_sp->AppendProperty( 743b9c1b51eSKate Stone ConstString("interpreter"), 744754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 745d5b44036SJonas Devlieghere true, m_command_interpreter_up->GetValueProperties()); 746754a9369SGreg Clayton } 747b9c1b51eSKate Stone OptionValueSInt64 *term_width = 748b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64( 749b9c1b51eSKate Stone nullptr, ePropertyTerminalWidth); 75067cc0636SGreg Clayton term_width->SetMinimumValue(10); 75167cc0636SGreg Clayton term_width->SetMaximumValue(1024); 752c3ce7f27SMichael Sartain 753c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 754c3ce7f27SMichael Sartain const char *term = getenv("TERM"); 755c3ce7f27SMichael Sartain if (term && !strcmp(term, "dumb")) 756c3ce7f27SMichael Sartain SetUseColor(false); 757eca9ce14SRaphael Isemann // Turn off use-color if we don't write to a terminal with color support. 7587ca15ba7SLawrence D'Anna if (!GetOutputFile().GetIsTerminalWithColors()) 759eca9ce14SRaphael Isemann SetUseColor(false); 7608aa23614SDavid Bolvansky 7618aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) 7628aa23614SDavid Bolvansky // Enabling use of ANSI color codes because LLDB is using them to highlight 7638aa23614SDavid Bolvansky // text. 7648aa23614SDavid Bolvansky llvm::sys::Process::UseANSIEscapeCodes(true); 7658aa23614SDavid Bolvansky #endif 76630fdc8d8SChris Lattner } 76730fdc8d8SChris Lattner 768b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); } 7698314c525SJim Ingham 770b9c1b51eSKate Stone void Debugger::Clear() { 77105097246SAdrian Prantl // Make sure we call this function only once. With the C++ global destructor 77205097246SAdrian Prantl // chain having a list of debuggers and with code that can be running on 77305097246SAdrian Prantl // other threads, we need to ensure this doesn't happen multiple times. 7744329fe42SGreg Clayton // 7754329fe42SGreg Clayton // The following functions call Debugger::Clear(): 7764329fe42SGreg Clayton // Debugger::~Debugger(); 7774329fe42SGreg Clayton // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp); 7784329fe42SGreg Clayton // static void Debugger::Terminate(); 779c5f28e2aSKamil Rytarowski llvm::call_once(m_clear_once, [this]() { 78044d93782SGreg Clayton ClearIOHandlers(); 78144d93782SGreg Clayton StopIOHandlerThread(); 78244d93782SGreg Clayton StopEventHandlerThread(); 783583bbb1dSJim Ingham m_listener_sp->Clear(); 7846611103cSGreg Clayton int num_targets = m_target_list.GetNumTargets(); 785b9c1b51eSKate Stone for (int i = 0; i < num_targets; i++) { 786ccbc08e6SGreg Clayton TargetSP target_sp(m_target_list.GetTargetAtIndex(i)); 787b9c1b51eSKate Stone if (target_sp) { 788ccbc08e6SGreg Clayton ProcessSP process_sp(target_sp->GetProcessSP()); 7896611103cSGreg Clayton if (process_sp) 7901fd07059SJim Ingham process_sp->Finalize(); 791ccbc08e6SGreg Clayton target_sp->Destroy(); 7926611103cSGreg Clayton } 79330fdc8d8SChris Lattner } 794583bbb1dSJim Ingham m_broadcaster_manager_sp->Clear(); 79530fdc8d8SChris Lattner 796b9c1b51eSKate Stone // Close the input file _before_ we close the input read communications 79705097246SAdrian Prantl // class as it does NOT own the input file, our m_input_file does. 798c5917d9aSJim Ingham m_terminal_state.Clear(); 7997ca15ba7SLawrence D'Anna GetInputFile().Close(); 8000c4129f2SGreg Clayton 801d5b44036SJonas Devlieghere m_command_interpreter_up->Clear(); 8024329fe42SGreg Clayton }); 8038314c525SJim Ingham } 80430fdc8d8SChris Lattner 805b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const { 80644d93782SGreg Clayton // return m_input_comm.GetCloseOnEOF(); 80744d93782SGreg Clayton return false; 808fc3f027dSGreg Clayton } 809fc3f027dSGreg Clayton 810b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) { 81144d93782SGreg Clayton // m_input_comm.SetCloseOnEOF(b); 812fc3f027dSGreg Clayton } 813fc3f027dSGreg Clayton 814b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() { 815d5b44036SJonas Devlieghere return !m_command_interpreter_up->GetSynchronous(); 81630fdc8d8SChris Lattner } 81730fdc8d8SChris Lattner 818b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) { 819d5b44036SJonas Devlieghere m_command_interpreter_up->SetSynchronous(!async_execution); 82030fdc8d8SChris Lattner } 82130fdc8d8SChris Lattner 822d77c2e09SJonas Devlieghere repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; } 823d77c2e09SJonas Devlieghere 82496898eb6SLawrence D'Anna void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) { 82596898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 826d77c2e09SJonas Devlieghere m_input_recorder = recorder; 82796898eb6SLawrence D'Anna m_input_file_sp = file_sp; 82805097246SAdrian Prantl // Save away the terminal state if that is relevant, so that we can restore 82905097246SAdrian Prantl // it in RestoreInputState. 830c5917d9aSJim Ingham SaveInputTerminalState(); 83130fdc8d8SChris Lattner } 83230fdc8d8SChris Lattner 83396898eb6SLawrence D'Anna void Debugger::SetOutputFile(FileSP file_sp) { 83496898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 8357ca15ba7SLawrence D'Anna m_output_stream_sp = std::make_shared<StreamFile>(file_sp); 83630fdc8d8SChris Lattner } 83730fdc8d8SChris Lattner 83896898eb6SLawrence D'Anna void Debugger::SetErrorFile(FileSP file_sp) { 83996898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 8407ca15ba7SLawrence D'Anna m_error_stream_sp = std::make_shared<StreamFile>(file_sp); 84130fdc8d8SChris Lattner } 84230fdc8d8SChris Lattner 843b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() { 8447ca15ba7SLawrence D'Anna int fd = GetInputFile().GetDescriptor(); 8457ca15ba7SLawrence D'Anna if (fd != File::kInvalidDescriptor) 8467ca15ba7SLawrence D'Anna m_terminal_state.Save(fd, true); 84744d93782SGreg Clayton } 848c5917d9aSJim Ingham 849b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } 850c5917d9aSJim Ingham 851b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() { 85230fdc8d8SChris Lattner ExecutionContext exe_ctx; 853c14ee32dSGreg Clayton TargetSP target_sp(GetSelectedTarget()); 854c14ee32dSGreg Clayton exe_ctx.SetTargetSP(target_sp); 85530fdc8d8SChris Lattner 856b9c1b51eSKate Stone if (target_sp) { 857c14ee32dSGreg Clayton ProcessSP process_sp(target_sp->GetProcessSP()); 858c14ee32dSGreg Clayton exe_ctx.SetProcessSP(process_sp); 859b9c1b51eSKate Stone if (process_sp && !process_sp->IsRunning()) { 860c14ee32dSGreg Clayton ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread()); 861b9c1b51eSKate Stone if (thread_sp) { 862c14ee32dSGreg Clayton exe_ctx.SetThreadSP(thread_sp); 863c14ee32dSGreg Clayton exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame()); 864df370550SEugene Zelenko if (exe_ctx.GetFramePtr() == nullptr) 865c14ee32dSGreg Clayton exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0)); 86630fdc8d8SChris Lattner } 86730fdc8d8SChris Lattner } 86830fdc8d8SChris Lattner } 86930fdc8d8SChris Lattner return exe_ctx; 87030fdc8d8SChris Lattner } 87130fdc8d8SChris Lattner 872b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() { 87316ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 87444d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 875efed6131SCaroline Tice if (reader_sp) 87644d93782SGreg Clayton reader_sp->Interrupt(); 877efed6131SCaroline Tice } 878efed6131SCaroline Tice 879b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() { 88016ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 88144d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 882efed6131SCaroline Tice if (reader_sp) 88344d93782SGreg Clayton reader_sp->GotEOF(); 884efed6131SCaroline Tice } 885efed6131SCaroline Tice 886b9c1b51eSKate Stone void Debugger::ClearIOHandlers() { 887b9c1b51eSKate Stone // The bottom input reader should be the main debugger input reader. We do 888b9c1b51eSKate Stone // not want to close that one here. 88916ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 890b9c1b51eSKate Stone while (m_input_reader_stack.GetSize() > 1) { 89144d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 8923d6086f6SCaroline Tice if (reader_sp) 8934446487dSPavel Labath PopIOHandler(reader_sp); 8943d6086f6SCaroline Tice } 8953d6086f6SCaroline Tice } 8963d6086f6SCaroline Tice 897b9c1b51eSKate Stone void Debugger::ExecuteIOHandlers() { 898b9c1b51eSKate Stone while (true) { 89944d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 90030fdc8d8SChris Lattner if (!reader_sp) 90130fdc8d8SChris Lattner break; 90230fdc8d8SChris Lattner 90344d93782SGreg Clayton reader_sp->Run(); 90444d93782SGreg Clayton 90544d93782SGreg Clayton // Remove all input readers that are done from the top of the stack 906b9c1b51eSKate Stone while (true) { 90744d93782SGreg Clayton IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); 90844d93782SGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 9094446487dSPavel Labath PopIOHandler(top_reader_sp); 91030fdc8d8SChris Lattner else 91130fdc8d8SChris Lattner break; 91230fdc8d8SChris Lattner } 91330fdc8d8SChris Lattner } 91444d93782SGreg Clayton ClearIOHandlers(); 91544d93782SGreg Clayton } 91630fdc8d8SChris Lattner 917b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) { 91844d93782SGreg Clayton return m_input_reader_stack.IsTop(reader_sp); 91944d93782SGreg Clayton } 92030fdc8d8SChris Lattner 921b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, 922b9c1b51eSKate Stone IOHandler::Type second_top_type) { 9236681041dSSean Callanan return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type); 9246681041dSSean Callanan } 9256681041dSSean Callanan 926b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { 9277ca15ba7SLawrence D'Anna lldb_private::StreamFile &stream = 9287ca15ba7SLawrence D'Anna is_stdout ? GetOutputStream() : GetErrorStream(); 9297ca15ba7SLawrence D'Anna m_input_reader_stack.PrintAsync(&stream, s, len); 9304446487dSPavel Labath } 93144d93782SGreg Clayton 932b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { 93344d93782SGreg Clayton return m_input_reader_stack.GetTopIOHandlerControlSequence(ch); 93430fdc8d8SChris Lattner } 93530fdc8d8SChris Lattner 936b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() { 937a487aa4cSKate Stone return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); 938a487aa4cSKate Stone } 939a487aa4cSKate Stone 940b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() { 941a487aa4cSKate Stone return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); 942a487aa4cSKate Stone } 943a487aa4cSKate Stone 944b9c1b51eSKate Stone void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) { 94544d93782SGreg Clayton PushIOHandler(reader_sp); 946577508dfSGreg Clayton 947577508dfSGreg Clayton IOHandlerSP top_reader_sp = reader_sp; 948b9c1b51eSKate Stone while (top_reader_sp) { 949577508dfSGreg Clayton top_reader_sp->Run(); 950577508dfSGreg Clayton 951b9c1b51eSKate Stone if (top_reader_sp.get() == reader_sp.get()) { 952577508dfSGreg Clayton if (PopIOHandler(reader_sp)) 953577508dfSGreg Clayton break; 954577508dfSGreg Clayton } 955577508dfSGreg Clayton 956b9c1b51eSKate Stone while (true) { 957577508dfSGreg Clayton top_reader_sp = m_input_reader_stack.Top(); 958577508dfSGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 9594446487dSPavel Labath PopIOHandler(top_reader_sp); 960577508dfSGreg Clayton else 961577508dfSGreg Clayton break; 962577508dfSGreg Clayton } 963577508dfSGreg Clayton } 96444d93782SGreg Clayton } 96544d93782SGreg Clayton 9667ca15ba7SLawrence D'Anna void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out, 967b9c1b51eSKate Stone StreamFileSP &err) { 96805097246SAdrian Prantl // Before an IOHandler runs, it must have in/out/err streams. This function 96905097246SAdrian Prantl // is called when one ore more of the streams are nullptr. We use the top 97005097246SAdrian Prantl // input reader's in/out/err streams, or fall back to the debugger file 97105097246SAdrian Prantl // handles, or we fall back onto stdin/stdout/stderr as a last resort. 97244d93782SGreg Clayton 97316ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 97444d93782SGreg Clayton IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); 97544d93782SGreg Clayton // If no STDIN has been set, then set it appropriately 976b07823f3SLawrence D'Anna if (!in || !in->IsValid()) { 97744d93782SGreg Clayton if (top_reader_sp) 9787ca15ba7SLawrence D'Anna in = top_reader_sp->GetInputFileSP(); 97944d93782SGreg Clayton else 9807ca15ba7SLawrence D'Anna in = GetInputFileSP(); 98144d93782SGreg Clayton // If there is nothing, use stdin 98244d93782SGreg Clayton if (!in) 983f913fd6eSLawrence D'Anna in = std::make_shared<NativeFile>(stdin, false); 98444d93782SGreg Clayton } 98544d93782SGreg Clayton // If no STDOUT has been set, then set it appropriately 986b07823f3SLawrence D'Anna if (!out || !out->GetFile().IsValid()) { 98744d93782SGreg Clayton if (top_reader_sp) 9887ca15ba7SLawrence D'Anna out = top_reader_sp->GetOutputStreamFileSP(); 98944d93782SGreg Clayton else 9907ca15ba7SLawrence D'Anna out = GetOutputStreamSP(); 99144d93782SGreg Clayton // If there is nothing, use stdout 99244d93782SGreg Clayton if (!out) 9932f3df613SZachary Turner out = std::make_shared<StreamFile>(stdout, false); 99444d93782SGreg Clayton } 99544d93782SGreg Clayton // If no STDERR has been set, then set it appropriately 996b07823f3SLawrence D'Anna if (!err || !err->GetFile().IsValid()) { 99744d93782SGreg Clayton if (top_reader_sp) 9987ca15ba7SLawrence D'Anna err = top_reader_sp->GetErrorStreamFileSP(); 99944d93782SGreg Clayton else 10007ca15ba7SLawrence D'Anna err = GetErrorStreamSP(); 100144d93782SGreg Clayton // If there is nothing, use stderr 100244d93782SGreg Clayton if (!err) 10037ca15ba7SLawrence D'Anna err = std::make_shared<StreamFile>(stderr, false); 100444d93782SGreg Clayton } 100544d93782SGreg Clayton } 100644d93782SGreg Clayton 1007c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp, 1008c01783a8SRaphael Isemann bool cancel_top_handler) { 100930fdc8d8SChris Lattner if (!reader_sp) 101030fdc8d8SChris Lattner return; 1011b44880caSCaroline Tice 101216ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 10134446487dSPavel Labath 10144446487dSPavel Labath // Get the current top input reader... 101544d93782SGreg Clayton IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); 1016b44880caSCaroline Tice 1017b4874f1aSGreg Clayton // Don't push the same IO handler twice... 10184446487dSPavel Labath if (reader_sp == top_reader_sp) 10194446487dSPavel Labath return; 10204446487dSPavel Labath 102144d93782SGreg Clayton // Push our new input reader 1022d5a0a01bSCaroline Tice m_input_reader_stack.Push(reader_sp); 10234446487dSPavel Labath reader_sp->Activate(); 102444d93782SGreg Clayton 102505097246SAdrian Prantl // Interrupt the top input reader to it will exit its Run() function and let 102605097246SAdrian Prantl // this new input reader take over 1027b9c1b51eSKate Stone if (top_reader_sp) { 102844d93782SGreg Clayton top_reader_sp->Deactivate(); 1029c01783a8SRaphael Isemann if (cancel_top_handler) 10304446487dSPavel Labath top_reader_sp->Cancel(); 103130fdc8d8SChris Lattner } 1032b4874f1aSGreg Clayton } 103330fdc8d8SChris Lattner 1034b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) { 10354446487dSPavel Labath if (!pop_reader_sp) 10364446487dSPavel Labath return false; 103730fdc8d8SChris Lattner 103816ff8604SSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); 103944d93782SGreg Clayton 104005097246SAdrian Prantl // The reader on the stop of the stack is done, so let the next read on the 104105097246SAdrian Prantl // stack refresh its prompt and if there is one... 10424446487dSPavel Labath if (m_input_reader_stack.IsEmpty()) 10434446487dSPavel Labath return false; 10444446487dSPavel Labath 104544d93782SGreg Clayton IOHandlerSP reader_sp(m_input_reader_stack.Top()); 104630fdc8d8SChris Lattner 10474446487dSPavel Labath if (pop_reader_sp != reader_sp) 10484446487dSPavel Labath return false; 10494446487dSPavel Labath 105044d93782SGreg Clayton reader_sp->Deactivate(); 1051b4874f1aSGreg Clayton reader_sp->Cancel(); 1052d5a0a01bSCaroline Tice m_input_reader_stack.Pop(); 105330fdc8d8SChris Lattner 1054d5a0a01bSCaroline Tice reader_sp = m_input_reader_stack.Top(); 105530fdc8d8SChris Lattner if (reader_sp) 105644d93782SGreg Clayton reader_sp->Activate(); 105744d93782SGreg Clayton 105844d93782SGreg Clayton return true; 105930fdc8d8SChris Lattner } 10606611103cSGreg Clayton 1061b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() { 10622f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, true); 10635b52f0c7SJim Ingham } 10645b52f0c7SJim Ingham 1065b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() { 10662f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, false); 10675b52f0c7SJim Ingham } 10685b52f0c7SJim Ingham 1069b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() { 1070b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 10716c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 10726c42e063SGreg Clayton return g_debugger_list_ptr->size(); 1073061858ceSEnrico Granata } 1074c15f55e2SGreg Clayton return 0; 1075c15f55e2SGreg Clayton } 1076061858ceSEnrico Granata 1077b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) { 1078061858ceSEnrico Granata DebuggerSP debugger_sp; 1079061858ceSEnrico Granata 1080b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 10816c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 10826c42e063SGreg Clayton if (index < g_debugger_list_ptr->size()) 10836c42e063SGreg Clayton debugger_sp = g_debugger_list_ptr->at(index); 1084c15f55e2SGreg Clayton } 1085061858ceSEnrico Granata 1086061858ceSEnrico Granata return debugger_sp; 1087061858ceSEnrico Granata } 1088061858ceSEnrico Granata 1089b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) { 10904d122c40SGreg Clayton DebuggerSP debugger_sp; 1091ebc1bb27SCaroline Tice 1092b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 10936c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 10946c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 1095b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 1096b9c1b51eSKate Stone if ((*pos)->GetID() == id) { 1097ebc1bb27SCaroline Tice debugger_sp = *pos; 1098ebc1bb27SCaroline Tice break; 1099ebc1bb27SCaroline Tice } 1100ebc1bb27SCaroline Tice } 1101c15f55e2SGreg Clayton } 1102ebc1bb27SCaroline Tice return debugger_sp; 1103ebc1bb27SCaroline Tice } 11043df9a8dfSCaroline Tice 1105b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, 1106aff1b357SJason Molenda const SymbolContext *sc, 1107aff1b357SJason Molenda const SymbolContext *prev_sc, 1108aff1b357SJason Molenda const ExecutionContext *exe_ctx, 1109b9c1b51eSKate Stone const Address *addr, Stream &s) { 1110554f68d3SGreg Clayton FormatEntity::Entry format_entry; 1111554f68d3SGreg Clayton 1112b9c1b51eSKate Stone if (format == nullptr) { 1113df370550SEugene Zelenko if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) 1114aff1b357SJason Molenda format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1115b9c1b51eSKate Stone if (format == nullptr) { 1116554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format_entry); 1117554f68d3SGreg Clayton format = &format_entry; 1118554f68d3SGreg Clayton } 1119aff1b357SJason Molenda } 1120aff1b357SJason Molenda bool function_changed = false; 1121aff1b357SJason Molenda bool initial_function = false; 1122b9c1b51eSKate Stone if (prev_sc && (prev_sc->function || prev_sc->symbol)) { 1123b9c1b51eSKate Stone if (sc && (sc->function || sc->symbol)) { 1124b9c1b51eSKate Stone if (prev_sc->symbol && sc->symbol) { 1125b9c1b51eSKate Stone if (!sc->symbol->Compare(prev_sc->symbol->GetName(), 1126b9c1b51eSKate Stone prev_sc->symbol->GetType())) { 1127aff1b357SJason Molenda function_changed = true; 1128aff1b357SJason Molenda } 1129b9c1b51eSKate Stone } else if (prev_sc->function && sc->function) { 1130b9c1b51eSKate Stone if (prev_sc->function->GetMangled() != sc->function->GetMangled()) { 1131aff1b357SJason Molenda function_changed = true; 1132aff1b357SJason Molenda } 1133aff1b357SJason Molenda } 1134aff1b357SJason Molenda } 1135aff1b357SJason Molenda } 113605097246SAdrian Prantl // The first context on a list of instructions will have a prev_sc that has 113705097246SAdrian Prantl // no Function or Symbol -- if SymbolContext had an IsValid() method, it 1138aff1b357SJason Molenda // would return false. But we do get a prev_sc pointer. 1139b9c1b51eSKate Stone if ((sc && (sc->function || sc->symbol)) && prev_sc && 1140b9c1b51eSKate Stone (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) { 1141aff1b357SJason Molenda initial_function = true; 1142aff1b357SJason Molenda } 1143b9c1b51eSKate Stone return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, 1144b9c1b51eSKate Stone function_changed, initial_function); 1145aff1b357SJason Molenda } 1146aff1b357SJason Molenda 1147b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, 1148b9c1b51eSKate Stone void *baton) { 11494f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 11504f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 11514f02b22dSJim Ingham // callback. 11522f3df613SZachary Turner m_log_callback_stream_sp = 11532f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 1154228063cdSJim Ingham } 1155228063cdSJim Ingham 11565e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel, 11575e336903SPavel Labath llvm::ArrayRef<const char *> categories, 11585e336903SPavel Labath llvm::StringRef log_file, uint32_t log_options, 1159775588c0SPavel Labath llvm::raw_ostream &error_stream) { 11605fae71c5SPavel Labath const bool should_close = true; 11615fae71c5SPavel Labath const bool unbuffered = true; 11625fae71c5SPavel Labath 11635fae71c5SPavel Labath std::shared_ptr<llvm::raw_ostream> log_stream_sp; 1164b9c1b51eSKate Stone if (m_log_callback_stream_sp) { 1165228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 1166228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 1167b9c1b51eSKate Stone log_options |= 1168b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 11695e336903SPavel Labath } else if (log_file.empty()) { 11705fae71c5SPavel Labath log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( 11717ca15ba7SLawrence D'Anna GetOutputFile().GetDescriptor(), !should_close, unbuffered); 1172b9c1b51eSKate Stone } else { 11735fae71c5SPavel Labath auto pos = m_log_streams.find(log_file); 1174c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 1175c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 1176b9c1b51eSKate Stone if (!log_stream_sp) { 1177d9b948b6SFangrui Song llvm::sys::fs::OpenFlags flags = llvm::sys::fs::OF_Text; 11785fae71c5SPavel Labath if (log_options & LLDB_LOG_OPTION_APPEND) 1179d9b948b6SFangrui Song flags |= llvm::sys::fs::OF_Append; 11805fae71c5SPavel Labath int FD; 11811f67a3cbSZachary Turner if (std::error_code ec = llvm::sys::fs::openFileForWrite( 11821f67a3cbSZachary Turner log_file, FD, llvm::sys::fs::CD_CreateAlways, flags)) { 1183775588c0SPavel Labath error_stream << "Unable to open log file: " << ec.message(); 11845fae71c5SPavel Labath return false; 11855fae71c5SPavel Labath } 11862f3df613SZachary Turner log_stream_sp = 11872f3df613SZachary Turner std::make_shared<llvm::raw_fd_ostream>(FD, should_close, unbuffered); 1188228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 1189228063cdSJim Ingham } 1190228063cdSJim Ingham } 1191df370550SEugene Zelenko assert(log_stream_sp); 1192228063cdSJim Ingham 1193228063cdSJim Ingham if (log_options == 0) 1194b9c1b51eSKate Stone log_options = 1195b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 1196228063cdSJim Ingham 1197b9c1b51eSKate Stone return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories, 1198b9c1b51eSKate Stone error_stream); 1199228063cdSJim Ingham } 1200228063cdSJim Ingham 1201*bbf70c04SJonas Devlieghere ScriptInterpreter * 1202*bbf70c04SJonas Devlieghere Debugger::GetScriptInterpreter(bool can_create, 1203*bbf70c04SJonas Devlieghere llvm::Optional<lldb::ScriptLanguage> language) { 12042b29b432SJonas Devlieghere std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex); 1205*bbf70c04SJonas Devlieghere lldb::ScriptLanguage script_language = 1206*bbf70c04SJonas Devlieghere language ? *language : GetScriptLanguage(); 12072b29b432SJonas Devlieghere 1208*bbf70c04SJonas Devlieghere if (!m_script_interpreters[script_language]) { 12092b29b432SJonas Devlieghere if (!can_create) 12102b29b432SJonas Devlieghere return nullptr; 1211*bbf70c04SJonas Devlieghere m_script_interpreters[script_language] = 1212*bbf70c04SJonas Devlieghere PluginManager::GetScriptInterpreterForLanguage(script_language, *this); 12132b29b432SJonas Devlieghere } 12142b29b432SJonas Devlieghere 1215*bbf70c04SJonas Devlieghere return m_script_interpreters[script_language].get(); 12162b29b432SJonas Devlieghere } 12172b29b432SJonas Devlieghere 1218b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() { 1219d5b44036SJonas Devlieghere if (!m_source_manager_up) 1220a8f3ae7cSJonas Devlieghere m_source_manager_up = std::make_unique<SourceManager>(shared_from_this()); 1221d5b44036SJonas Devlieghere return *m_source_manager_up; 12229585fbfcSGreg Clayton } 12239585fbfcSGreg Clayton 122444d93782SGreg Clayton // This function handles events that were broadcast by the process. 1225b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) { 122644d93782SGreg Clayton using namespace lldb; 1227b9c1b51eSKate Stone const uint32_t event_type = 1228b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 1229b9c1b51eSKate Stone event_sp); 123044d93782SGreg Clayton 123144d93782SGreg Clayton // if (event_type & eBreakpointEventTypeAdded 123244d93782SGreg Clayton // || event_type & eBreakpointEventTypeRemoved 123344d93782SGreg Clayton // || event_type & eBreakpointEventTypeEnabled 123444d93782SGreg Clayton // || event_type & eBreakpointEventTypeDisabled 123544d93782SGreg Clayton // || event_type & eBreakpointEventTypeCommandChanged 123644d93782SGreg Clayton // || event_type & eBreakpointEventTypeConditionChanged 123744d93782SGreg Clayton // || event_type & eBreakpointEventTypeIgnoreChanged 123844d93782SGreg Clayton // || event_type & eBreakpointEventTypeLocationsResolved) 123944d93782SGreg Clayton // { 1240b9c1b51eSKate Stone // // Don't do anything about these events, since the breakpoint 1241b9c1b51eSKate Stone // commands already echo these actions. 124244d93782SGreg Clayton // } 124344d93782SGreg Clayton // 1244b9c1b51eSKate Stone if (event_type & eBreakpointEventTypeLocationsAdded) { 1245b9c1b51eSKate Stone uint32_t num_new_locations = 1246b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 1247b9c1b51eSKate Stone event_sp); 1248b9c1b51eSKate Stone if (num_new_locations > 0) { 1249b9c1b51eSKate Stone BreakpointSP breakpoint = 1250b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 12514446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1252b9c1b51eSKate Stone if (output_sp) { 125344d93782SGreg Clayton output_sp->Printf("%d location%s added to breakpoint %d\n", 1254b9c1b51eSKate Stone num_new_locations, num_new_locations == 1 ? "" : "s", 125544d93782SGreg Clayton breakpoint->GetID()); 12564446487dSPavel Labath output_sp->Flush(); 125744d93782SGreg Clayton } 125844d93782SGreg Clayton } 125944d93782SGreg Clayton } 126044d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsRemoved) 126144d93782SGreg Clayton // { 1262b9c1b51eSKate Stone // // These locations just get disabled, not sure it is worth spamming 1263b9c1b51eSKate Stone // folks about this on the command line. 126444d93782SGreg Clayton // } 126544d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsResolved) 126644d93782SGreg Clayton // { 1267b9c1b51eSKate Stone // // This might be an interesting thing to note, but I'm going to 1268b9c1b51eSKate Stone // leave it quiet for now, it just looked noisy. 126944d93782SGreg Clayton // } 127044d93782SGreg Clayton } 127144d93782SGreg Clayton 1272a9d58436SPavel Labath void Debugger::FlushProcessOutput(Process &process, bool flush_stdout, 1273a9d58436SPavel Labath bool flush_stderr) { 1274a9d58436SPavel Labath const auto &flush = [&](Stream &stream, 1275a9d58436SPavel Labath size_t (Process::*get)(char *, size_t, Status &)) { 127697206d57SZachary Turner Status error; 127744d93782SGreg Clayton size_t len; 1278a9d58436SPavel Labath char buffer[1024]; 1279a9d58436SPavel Labath while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0) 1280a9d58436SPavel Labath stream.Write(buffer, len); 1281a9d58436SPavel Labath stream.Flush(); 1282a9d58436SPavel Labath }; 128344d93782SGreg Clayton 1284a9d58436SPavel Labath std::lock_guard<std::mutex> guard(m_output_flush_mutex); 1285a9d58436SPavel Labath if (flush_stdout) 1286a9d58436SPavel Labath flush(*GetAsyncOutputStream(), &Process::GetSTDOUT); 1287a9d58436SPavel Labath if (flush_stderr) 1288a9d58436SPavel Labath flush(*GetAsyncErrorStream(), &Process::GetSTDERR); 128944d93782SGreg Clayton } 129044d93782SGreg Clayton 129144d93782SGreg Clayton // This function handles events that were broadcast by the process. 1292b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) { 129344d93782SGreg Clayton using namespace lldb; 129444d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 1295b9c1b51eSKate Stone ProcessSP process_sp = 1296b9c1b51eSKate Stone (event_type == Process::eBroadcastBitStructuredData) 129775930019STodd Fiala ? EventDataStructuredData::GetProcessFromEvent(event_sp.get()) 129875930019STodd Fiala : Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 129944d93782SGreg Clayton 13004446487dSPavel Labath StreamSP output_stream_sp = GetAsyncOutputStream(); 13014446487dSPavel Labath StreamSP error_stream_sp = GetAsyncErrorStream(); 130244d93782SGreg Clayton const bool gui_enabled = IsForwardingEvents(); 130344d93782SGreg Clayton 1304b9c1b51eSKate Stone if (!gui_enabled) { 1305b4874f1aSGreg Clayton bool pop_process_io_handler = false; 130644d93782SGreg Clayton assert(process_sp); 130744d93782SGreg Clayton 13084446487dSPavel Labath bool state_is_stopped = false; 1309b9c1b51eSKate Stone const bool got_state_changed = 1310b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStateChanged) != 0; 13114446487dSPavel Labath const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0; 13124446487dSPavel Labath const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0; 1313b9c1b51eSKate Stone const bool got_structured_data = 1314b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStructuredData) != 0; 131575930019STodd Fiala 1316b9c1b51eSKate Stone if (got_state_changed) { 1317b9c1b51eSKate Stone StateType event_state = 1318b9c1b51eSKate Stone Process::ProcessEventData::GetStateFromEvent(event_sp.get()); 13194446487dSPavel Labath state_is_stopped = StateIsStoppedState(event_state, false); 132044d93782SGreg Clayton } 1321b4874f1aSGreg Clayton 13224446487dSPavel Labath // Display running state changes first before any STDIO 1323b9c1b51eSKate Stone if (got_state_changed && !state_is_stopped) { 1324b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1325b9c1b51eSKate Stone pop_process_io_handler); 132644d93782SGreg Clayton } 1327b4874f1aSGreg Clayton 1328a9d58436SPavel Labath // Now display STDOUT and STDERR 1329a9d58436SPavel Labath FlushProcessOutput(*process_sp, got_stdout || got_state_changed, 1330a9d58436SPavel Labath got_stderr || got_state_changed); 1331b4874f1aSGreg Clayton 133275930019STodd Fiala // Give structured data events an opportunity to display. 1333b9c1b51eSKate Stone if (got_structured_data) { 133475930019STodd Fiala StructuredDataPluginSP plugin_sp = 133575930019STodd Fiala EventDataStructuredData::GetPluginFromEvent(event_sp.get()); 1336b9c1b51eSKate Stone if (plugin_sp) { 133775930019STodd Fiala auto structured_data_sp = 133875930019STodd Fiala EventDataStructuredData::GetObjectFromEvent(event_sp.get()); 1339b9c1b51eSKate Stone if (output_stream_sp) { 134075930019STodd Fiala StreamString content_stream; 134197206d57SZachary Turner Status error = 1342b9c1b51eSKate Stone plugin_sp->GetDescription(structured_data_sp, content_stream); 1343b9c1b51eSKate Stone if (error.Success()) { 1344b9c1b51eSKate Stone if (!content_stream.GetString().empty()) { 134575930019STodd Fiala // Add newline. 134675930019STodd Fiala content_stream.PutChar('\n'); 134775930019STodd Fiala content_stream.Flush(); 134875930019STodd Fiala 134975930019STodd Fiala // Print it. 1350771ef6d4SMalcolm Parsons output_stream_sp->PutCString(content_stream.GetString()); 135175930019STodd Fiala } 1352b9c1b51eSKate Stone } else { 135375930019STodd Fiala error_stream_sp->Printf("Failed to print structured " 135475930019STodd Fiala "data with plugin %s: %s", 1355b9c1b51eSKate Stone plugin_sp->GetPluginName().AsCString(), 135675930019STodd Fiala error.AsCString()); 135775930019STodd Fiala } 135875930019STodd Fiala } 135975930019STodd Fiala } 136075930019STodd Fiala } 136175930019STodd Fiala 13624446487dSPavel Labath // Now display any stopped state changes after any STDIO 1363b9c1b51eSKate Stone if (got_state_changed && state_is_stopped) { 1364b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1365b9c1b51eSKate Stone pop_process_io_handler); 136644d93782SGreg Clayton } 136744d93782SGreg Clayton 13684446487dSPavel Labath output_stream_sp->Flush(); 13694446487dSPavel Labath error_stream_sp->Flush(); 137044d93782SGreg Clayton 1371b4874f1aSGreg Clayton if (pop_process_io_handler) 1372b4874f1aSGreg Clayton process_sp->PopProcessIOHandler(); 1373b4874f1aSGreg Clayton } 1374b4874f1aSGreg Clayton } 1375b4874f1aSGreg Clayton 1376b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) { 137705097246SAdrian Prantl // At present the only thread event we handle is the Frame Changed event, and 137805097246SAdrian Prantl // all we do for that is just reprint the thread status for that thread. 137944d93782SGreg Clayton using namespace lldb; 138044d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 13816a9767c7SJim Ingham const bool stop_format = true; 138244d93782SGreg Clayton if (event_type == Thread::eBroadcastBitStackChanged || 1383b9c1b51eSKate Stone event_type == Thread::eBroadcastBitThreadSelected) { 1384b9c1b51eSKate Stone ThreadSP thread_sp( 1385b9c1b51eSKate Stone Thread::ThreadEventData::GetThreadFromEvent(event_sp.get())); 1386b9c1b51eSKate Stone if (thread_sp) { 13876a9767c7SJim Ingham thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format); 138844d93782SGreg Clayton } 138944d93782SGreg Clayton } 139044d93782SGreg Clayton } 139144d93782SGreg Clayton 1392b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; } 139344d93782SGreg Clayton 1394b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) { 139544d93782SGreg Clayton m_forward_listener_sp = listener_sp; 139644d93782SGreg Clayton } 139744d93782SGreg Clayton 1398b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) { 139944d93782SGreg Clayton m_forward_listener_sp.reset(); 140044d93782SGreg Clayton } 140144d93782SGreg Clayton 1402b9c1b51eSKate Stone void Debugger::DefaultEventHandler() { 1403583bbb1dSJim Ingham ListenerSP listener_sp(GetListener()); 140444d93782SGreg Clayton ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 140544d93782SGreg Clayton ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 140644d93782SGreg Clayton ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 140744d93782SGreg Clayton BroadcastEventSpec target_event_spec(broadcaster_class_target, 140844d93782SGreg Clayton Target::eBroadcastBitBreakpointChanged); 140944d93782SGreg Clayton 1410b9c1b51eSKate Stone BroadcastEventSpec process_event_spec( 1411b9c1b51eSKate Stone broadcaster_class_process, 1412b9c1b51eSKate Stone Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT | 1413b9c1b51eSKate Stone Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData); 141444d93782SGreg Clayton 141544d93782SGreg Clayton BroadcastEventSpec thread_event_spec(broadcaster_class_thread, 141644d93782SGreg Clayton Thread::eBroadcastBitStackChanged | 141744d93782SGreg Clayton Thread::eBroadcastBitThreadSelected); 141844d93782SGreg Clayton 1419b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1420b9c1b51eSKate Stone target_event_spec); 1421b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1422b9c1b51eSKate Stone process_event_spec); 1423b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1424b9c1b51eSKate Stone thread_event_spec); 1425b9c1b51eSKate Stone listener_sp->StartListeningForEvents( 1426d5b44036SJonas Devlieghere m_command_interpreter_up.get(), 142744d93782SGreg Clayton CommandInterpreter::eBroadcastBitQuitCommandReceived | 142844d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousOutputData | 142944d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousErrorData); 143044d93782SGreg Clayton 143105097246SAdrian Prantl // Let the thread that spawned us know that we have started up and that we 143205097246SAdrian Prantl // are now listening to all required events so no events get missed 1433afa91e33SGreg Clayton m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); 1434afa91e33SGreg Clayton 143544d93782SGreg Clayton bool done = false; 1436b9c1b51eSKate Stone while (!done) { 143744d93782SGreg Clayton EventSP event_sp; 1438d35031e1SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 1439b9c1b51eSKate Stone if (event_sp) { 144044d93782SGreg Clayton Broadcaster *broadcaster = event_sp->GetBroadcaster(); 1441b9c1b51eSKate Stone if (broadcaster) { 144244d93782SGreg Clayton uint32_t event_type = event_sp->GetType(); 144344d93782SGreg Clayton ConstString broadcaster_class(broadcaster->GetBroadcasterClass()); 1444b9c1b51eSKate Stone if (broadcaster_class == broadcaster_class_process) { 144544d93782SGreg Clayton HandleProcessEvent(event_sp); 1446b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_target) { 1447b9c1b51eSKate Stone if (Breakpoint::BreakpointEventData::GetEventDataFromEvent( 1448b9c1b51eSKate Stone event_sp.get())) { 144944d93782SGreg Clayton HandleBreakpointEvent(event_sp); 145044d93782SGreg Clayton } 1451b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_thread) { 145244d93782SGreg Clayton HandleThreadEvent(event_sp); 1453d5b44036SJonas Devlieghere } else if (broadcaster == m_command_interpreter_up.get()) { 1454b9c1b51eSKate Stone if (event_type & 1455b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived) { 145644d93782SGreg Clayton done = true; 1457b9c1b51eSKate Stone } else if (event_type & 1458b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitAsynchronousErrorData) { 1459b9c1b51eSKate Stone const char *data = reinterpret_cast<const char *>( 1460b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1461b9c1b51eSKate Stone if (data && data[0]) { 14624446487dSPavel Labath StreamSP error_sp(GetAsyncErrorStream()); 1463b9c1b51eSKate Stone if (error_sp) { 146444d93782SGreg Clayton error_sp->PutCString(data); 146544d93782SGreg Clayton error_sp->Flush(); 146644d93782SGreg Clayton } 146744d93782SGreg Clayton } 1468b9c1b51eSKate Stone } else if (event_type & CommandInterpreter:: 1469b9c1b51eSKate Stone eBroadcastBitAsynchronousOutputData) { 1470b9c1b51eSKate Stone const char *data = reinterpret_cast<const char *>( 1471b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1472b9c1b51eSKate Stone if (data && data[0]) { 14734446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1474b9c1b51eSKate Stone if (output_sp) { 147544d93782SGreg Clayton output_sp->PutCString(data); 147644d93782SGreg Clayton output_sp->Flush(); 147744d93782SGreg Clayton } 147844d93782SGreg Clayton } 147944d93782SGreg Clayton } 148044d93782SGreg Clayton } 148144d93782SGreg Clayton } 148244d93782SGreg Clayton 148344d93782SGreg Clayton if (m_forward_listener_sp) 148444d93782SGreg Clayton m_forward_listener_sp->AddEvent(event_sp); 148544d93782SGreg Clayton } 148644d93782SGreg Clayton } 148744d93782SGreg Clayton } 148844d93782SGreg Clayton } 148944d93782SGreg Clayton 1490b9c1b51eSKate Stone lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) { 149144d93782SGreg Clayton ((Debugger *)arg)->DefaultEventHandler(); 149285200645SKonrad Kleine return {}; 149344d93782SGreg Clayton } 149444d93782SGreg Clayton 1495b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() { 1496b9c1b51eSKate Stone if (!m_event_handler_thread.IsJoinable()) { 149705097246SAdrian Prantl // We must synchronize with the DefaultEventHandler() thread to ensure it 149805097246SAdrian Prantl // is up and running and listening to events before we return from this 149905097246SAdrian Prantl // function. We do this by listening to events for the 1500afa91e33SGreg Clayton // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster 15011a728f66STatyana Krasnukha ConstString full_name("lldb.debugger.event-handler"); 15021a728f66STatyana Krasnukha ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString())); 1503b9c1b51eSKate Stone listener_sp->StartListeningForEvents(&m_sync_broadcaster, 1504b9c1b51eSKate Stone eBroadcastBitEventThreadIsListening); 1505afa91e33SGreg Clayton 15061a728f66STatyana Krasnukha auto thread_name = 1507e063ecccSJonas Devlieghere full_name.GetLength() < llvm::get_max_thread_name_length() 1508e063ecccSJonas Devlieghere ? full_name.AsCString() 1509e063ecccSJonas Devlieghere : "dbg.evt-handler"; 15101a728f66STatyana Krasnukha 15117c2896a2SZachary Turner // Use larger 8MB stack for this thread 1512f39c2e18SJonas Devlieghere llvm::Expected<HostThread> event_handler_thread = 1513f39c2e18SJonas Devlieghere ThreadLauncher::LaunchThread(thread_name, EventHandlerThread, this, 1514f39c2e18SJonas Devlieghere g_debugger_event_thread_stack_bytes); 1515f39c2e18SJonas Devlieghere 1516f39c2e18SJonas Devlieghere if (event_handler_thread) { 1517f39c2e18SJonas Devlieghere m_event_handler_thread = *event_handler_thread; 1518f39c2e18SJonas Devlieghere } else { 1519f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 1520f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 1521f39c2e18SJonas Devlieghere llvm::toString(event_handler_thread.takeError())); 1522f39c2e18SJonas Devlieghere } 1523afa91e33SGreg Clayton 152405097246SAdrian Prantl // Make sure DefaultEventHandler() is running and listening to events 152505097246SAdrian Prantl // before we return from this function. We are only listening for events of 152605097246SAdrian Prantl // type eBroadcastBitEventThreadIsListening so we don't need to check the 152705097246SAdrian Prantl // event, we just need to wait an infinite amount of time for it (nullptr 152805097246SAdrian Prantl // timeout as the first parameter) 1529afa91e33SGreg Clayton lldb::EventSP event_sp; 1530d35031e1SPavel Labath listener_sp->GetEvent(event_sp, llvm::None); 1531807b6b32SGreg Clayton } 1532acee96aeSZachary Turner return m_event_handler_thread.IsJoinable(); 153344d93782SGreg Clayton } 153444d93782SGreg Clayton 1535b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() { 1536b9c1b51eSKate Stone if (m_event_handler_thread.IsJoinable()) { 1537b9c1b51eSKate Stone GetCommandInterpreter().BroadcastEvent( 1538b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived); 153939de3110SZachary Turner m_event_handler_thread.Join(nullptr); 154044d93782SGreg Clayton } 154144d93782SGreg Clayton } 154244d93782SGreg Clayton 1543b9c1b51eSKate Stone lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) { 154444d93782SGreg Clayton Debugger *debugger = (Debugger *)arg; 15459aaab558SSiva Chandra debugger->ExecuteIOHandlers(); 154644d93782SGreg Clayton debugger->StopEventHandlerThread(); 154785200645SKonrad Kleine return {}; 154844d93782SGreg Clayton } 154944d93782SGreg Clayton 1550b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } 15516681041dSSean Callanan 1552b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() { 1553f39c2e18SJonas Devlieghere if (!m_io_handler_thread.IsJoinable()) { 1554f39c2e18SJonas Devlieghere llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread( 1555f39c2e18SJonas Devlieghere "lldb.debugger.io-handler", IOHandlerThread, this, 1556807b6b32SGreg Clayton 8 * 1024 * 1024); // Use larger 8MB stack for this thread 1557f39c2e18SJonas Devlieghere if (io_handler_thread) { 1558f39c2e18SJonas Devlieghere m_io_handler_thread = *io_handler_thread; 1559f39c2e18SJonas Devlieghere } else { 1560f39c2e18SJonas Devlieghere LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST), 1561f39c2e18SJonas Devlieghere "failed to launch host thread: {}", 1562f39c2e18SJonas Devlieghere llvm::toString(io_handler_thread.takeError())); 1563f39c2e18SJonas Devlieghere } 1564f39c2e18SJonas Devlieghere } 1565acee96aeSZachary Turner return m_io_handler_thread.IsJoinable(); 156644d93782SGreg Clayton } 156744d93782SGreg Clayton 1568b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() { 1569b9c1b51eSKate Stone if (m_io_handler_thread.IsJoinable()) { 15707ca15ba7SLawrence D'Anna GetInputFile().Close(); 157139de3110SZachary Turner m_io_handler_thread.Join(nullptr); 157244d93782SGreg Clayton } 157344d93782SGreg Clayton } 157444d93782SGreg Clayton 1575b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() { 1576b9c1b51eSKate Stone if (HasIOHandlerThread()) { 15776681041dSSean Callanan thread_result_t result; 15786681041dSSean Callanan m_io_handler_thread.Join(&result); 15796681041dSSean Callanan m_io_handler_thread = LLDB_INVALID_HOST_THREAD; 15806681041dSSean Callanan } 15816681041dSSean Callanan } 15826681041dSSean Callanan 1583b9c1b51eSKate Stone Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { 158433df7cd3SJim Ingham Target *target = nullptr; 1585b9c1b51eSKate Stone if (!prefer_dummy) { 158633df7cd3SJim Ingham target = m_target_list.GetSelectedTarget().get(); 158733df7cd3SJim Ingham if (target) 158833df7cd3SJim Ingham return target; 158933df7cd3SJim Ingham } 1590893c932aSJim Ingham 1591893c932aSJim Ingham return GetDummyTarget(); 1592893c932aSJim Ingham } 159344d93782SGreg Clayton 159497206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) { 159597206d57SZachary Turner Status err; 15963e7e915dSSean Callanan FileSpec repl_executable; 15973e7e915dSSean Callanan 1598b9c1b51eSKate Stone if (language == eLanguageTypeUnknown) { 1599aa97a89dSAdrian Prantl LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs(); 160097f84e87SSean Callanan 1601aa97a89dSAdrian Prantl if (auto single_lang = repl_languages.GetSingularLanguage()) { 1602aa97a89dSAdrian Prantl language = *single_lang; 1603aa97a89dSAdrian Prantl } else if (repl_languages.Empty()) { 1604b9c1b51eSKate Stone err.SetErrorStringWithFormat( 1605b9c1b51eSKate Stone "LLDB isn't configured with REPL support for any languages."); 160697f84e87SSean Callanan return err; 1607b9c1b51eSKate Stone } else { 1608b9c1b51eSKate Stone err.SetErrorStringWithFormat( 1609b9c1b51eSKate Stone "Multiple possible REPL languages. Please specify a language."); 161097f84e87SSean Callanan return err; 161197f84e87SSean Callanan } 161297f84e87SSean Callanan } 161397f84e87SSean Callanan 1614b9c1b51eSKate Stone Target *const target = 1615b9c1b51eSKate Stone nullptr; // passing in an empty target means the REPL must create one 16163e7e915dSSean Callanan 16173b682de6SSean Callanan REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); 16183e7e915dSSean Callanan 1619b9c1b51eSKate Stone if (!err.Success()) { 16203e7e915dSSean Callanan return err; 16213e7e915dSSean Callanan } 16223e7e915dSSean Callanan 1623b9c1b51eSKate Stone if (!repl_sp) { 1624b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't find a REPL for %s", 1625b9c1b51eSKate Stone Language::GetNameForLanguageType(language)); 16263e7e915dSSean Callanan return err; 16273e7e915dSSean Callanan } 16283e7e915dSSean Callanan 16293e7e915dSSean Callanan repl_sp->SetCompilerOptions(repl_options); 16303e7e915dSSean Callanan repl_sp->RunLoop(); 16313e7e915dSSean Callanan 16323e7e915dSSean Callanan return err; 16333e7e915dSSean Callanan } 1634