180814287SRaphael Isemann //===-- Debugger.cpp ------------------------------------------------------===// 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" 26d6b64612SMed Ismail Bennani #include "lldb/Interpreter/CommandReturnObject.h" 27672d2c12SJonas Devlieghere #include "lldb/Interpreter/OptionValue.h" 2846a28a95SJonas Devlieghere #include "lldb/Interpreter/OptionValueLanguage.h" 29633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 3067cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h" 3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 32672d2c12SJonas Devlieghere #include "lldb/Interpreter/Property.h" 33672d2c12SJonas Devlieghere #include "lldb/Interpreter/ScriptInterpreter.h" 341f746071SGreg Clayton #include "lldb/Symbol/Function.h" 351f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 36672d2c12SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h" 373e7e915dSSean Callanan #include "lldb/Target/Language.h" 3830fdc8d8SChris Lattner #include "lldb/Target/Process.h" 3975930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h" 4084a53dfbSEnrico Granata #include "lldb/Target/Target.h" 41b9c1b51eSKate Stone #include "lldb/Target/TargetList.h" 4230fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 43672d2c12SJonas Devlieghere #include "lldb/Target/ThreadList.h" 445a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 45181b823bSPavel Labath #include "lldb/Utility/Event.h" 46c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h" 47181b823bSPavel Labath #include "lldb/Utility/Listener.h" 48672d2c12SJonas Devlieghere #include "lldb/Utility/Log.h" 499e046f02SJonas Devlieghere #include "lldb/Utility/Reproducer.h" 50f23b829aSLevon Ter-Grigoryan #include "lldb/Utility/ReproducerProvider.h" 51d821c997SPavel Labath #include "lldb/Utility/State.h" 52672d2c12SJonas Devlieghere #include "lldb/Utility/Stream.h" 53fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h" 54bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 552f3df613SZachary Turner 56b1cb0b79SNico Weber #if defined(_WIN32) 57672d2c12SJonas Devlieghere #include "lldb/Host/windows/PosixApi.h" 588aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h" 592f3df613SZachary Turner #endif 602f3df613SZachary Turner 61672d2c12SJonas Devlieghere #include "llvm/ADT/None.h" 62672d2c12SJonas Devlieghere #include "llvm/ADT/STLExtras.h" 632f3df613SZachary Turner #include "llvm/ADT/StringRef.h" 64672d2c12SJonas Devlieghere #include "llvm/ADT/iterator.h" 652f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h" 662f3df613SZachary Turner #include "llvm/Support/FileSystem.h" 678aa23614SDavid Bolvansky #include "llvm/Support/Process.h" 682f3df613SZachary Turner #include "llvm/Support/Threading.h" 69672d2c12SJonas Devlieghere #include "llvm/Support/raw_ostream.h" 702f3df613SZachary Turner 7176e47d48SRaphael Isemann #include <cstdio> 7276e47d48SRaphael Isemann #include <cstdlib> 7376e47d48SRaphael Isemann #include <cstring> 74672d2c12SJonas Devlieghere #include <list> 75672d2c12SJonas Devlieghere #include <memory> 762f3df613SZachary Turner #include <mutex> 77672d2c12SJonas Devlieghere #include <set> 78672d2c12SJonas Devlieghere #include <string> 79672d2c12SJonas Devlieghere #include <system_error> 802f3df613SZachary Turner 81f23b829aSLevon Ter-Grigoryan // Includes for pipe() 82f23b829aSLevon Ter-Grigoryan #if defined(_WIN32) 83f23b829aSLevon Ter-Grigoryan #include <fcntl.h> 84f23b829aSLevon Ter-Grigoryan #include <io.h> 85f23b829aSLevon Ter-Grigoryan #else 86f23b829aSLevon Ter-Grigoryan #include <unistd.h> 87f23b829aSLevon Ter-Grigoryan #endif 88f23b829aSLevon Ter-Grigoryan 892f3df613SZachary Turner namespace lldb_private { 902f3df613SZachary Turner class Address; 912f3df613SZachary Turner } 9230fdc8d8SChris Lattner 9330fdc8d8SChris Lattner using namespace lldb; 9430fdc8d8SChris Lattner using namespace lldb_private; 9530fdc8d8SChris Lattner 96ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 977c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; 98ebc1bb27SCaroline Tice 991b654882SGreg Clayton #pragma mark Static Functions 1001b654882SGreg Clayton 1011b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 102b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr = 103b9c1b51eSKate Stone nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain 104b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr = 105b9c1b51eSKate Stone nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain 106e372b98dSGreg Clayton 1078fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { 108e063ecccSJonas Devlieghere { 109e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNever, 110e063ecccSJonas Devlieghere "never", 111e063ecccSJonas Devlieghere "Never show disassembly when displaying a stop context.", 112e063ecccSJonas Devlieghere }, 113e063ecccSJonas Devlieghere { 114e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoDebugInfo, 115e063ecccSJonas Devlieghere "no-debuginfo", 116e063ecccSJonas Devlieghere "Show disassembly when there is no debug information.", 117e063ecccSJonas Devlieghere }, 118e063ecccSJonas Devlieghere { 119e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoSource, 120e063ecccSJonas Devlieghere "no-source", 121e063ecccSJonas Devlieghere "Show disassembly when there is no source information, or the source " 122e063ecccSJonas Devlieghere "file " 123e063ecccSJonas Devlieghere "is missing when displaying a stop context.", 124e063ecccSJonas Devlieghere }, 125e063ecccSJonas Devlieghere { 126e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeAlways, 127e063ecccSJonas Devlieghere "always", 128e063ecccSJonas Devlieghere "Always show disassembly when displaying a stop context.", 129e063ecccSJonas Devlieghere }, 130e063ecccSJonas Devlieghere }; 131e372b98dSGreg Clayton 1328fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = { 133e063ecccSJonas Devlieghere { 134e063ecccSJonas Devlieghere eScriptLanguageNone, 135e063ecccSJonas Devlieghere "none", 136e063ecccSJonas Devlieghere "Disable scripting languages.", 137e063ecccSJonas Devlieghere }, 138e063ecccSJonas Devlieghere { 139e063ecccSJonas Devlieghere eScriptLanguagePython, 140e063ecccSJonas Devlieghere "python", 141e063ecccSJonas Devlieghere "Select python as the default scripting language.", 142e063ecccSJonas Devlieghere }, 143e063ecccSJonas Devlieghere { 144e063ecccSJonas Devlieghere eScriptLanguageDefault, 145e063ecccSJonas Devlieghere "default", 146e063ecccSJonas Devlieghere "Select the lldb default as the default scripting language.", 147e063ecccSJonas Devlieghere }, 148e063ecccSJonas Devlieghere }; 149e372b98dSGreg Clayton 1508fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement s_stop_show_column_values[] = { 151e063ecccSJonas Devlieghere { 152e063ecccSJonas Devlieghere eStopShowColumnAnsiOrCaret, 153e063ecccSJonas Devlieghere "ansi-or-caret", 154e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when color/ANSI " 155e063ecccSJonas Devlieghere "mode is enabled; otherwise, fall back to using a text-only caret (^) " 156e063ecccSJonas Devlieghere "as if \"caret-only\" mode was selected.", 157e063ecccSJonas Devlieghere }, 158e063ecccSJonas Devlieghere { 159e063ecccSJonas Devlieghere eStopShowColumnAnsi, 160e063ecccSJonas Devlieghere "ansi", 161e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when running LLDB " 162e063ecccSJonas Devlieghere "with color/ANSI enabled.", 163e063ecccSJonas Devlieghere }, 164e063ecccSJonas Devlieghere { 165e063ecccSJonas Devlieghere eStopShowColumnCaret, 166e063ecccSJonas Devlieghere "caret", 167e063ecccSJonas Devlieghere "Highlight the stop column with a caret character (^) underneath the " 168e063ecccSJonas Devlieghere "stop column. This method introduces a new line in source listings " 169e063ecccSJonas Devlieghere "that display thread stop locations.", 170e063ecccSJonas Devlieghere }, 171e063ecccSJonas Devlieghere { 172e063ecccSJonas Devlieghere eStopShowColumnNone, 173e063ecccSJonas Devlieghere "none", 174e063ecccSJonas Devlieghere "Do not highlight the stop column.", 175e063ecccSJonas Devlieghere }, 176e063ecccSJonas Devlieghere }; 1779666ba75STodd Fiala 178971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger 1796a253d37SJordan Rupprecht #include "CoreProperties.inc" 18067cc0636SGreg Clayton 181b9c1b51eSKate Stone enum { 182971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger 1836a253d37SJordan Rupprecht #include "CorePropertiesEnum.inc" 18467cc0636SGreg Clayton }; 18567cc0636SGreg Clayton 186df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr; 1874c05410fSGreg Clayton 18897206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, 1894c05410fSGreg Clayton VarSetOperationType op, 19097206d57SZachary Turner llvm::StringRef property_path, 19197206d57SZachary Turner llvm::StringRef value) { 192e063ecccSJonas Devlieghere bool is_load_script = 193e063ecccSJonas Devlieghere (property_path == "target.load-script-from-symbol-file"); 194e5814d78SRaphael Isemann // These properties might change how we visualize data. 195e5814d78SRaphael Isemann bool invalidate_data_vis = (property_path == "escape-non-printables"); 196e5814d78SRaphael Isemann invalidate_data_vis |= 197e5814d78SRaphael Isemann (property_path == "target.max-zero-padding-in-float-format"); 198e5814d78SRaphael Isemann if (invalidate_data_vis) { 199e5814d78SRaphael Isemann DataVisualization::ForceUpdate(); 200e5814d78SRaphael Isemann } 201e5814d78SRaphael Isemann 20284a53dfbSEnrico Granata TargetSP target_sp; 203397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 204b9c1b51eSKate Stone if (is_load_script && exe_ctx->GetTargetSP()) { 20584a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 206b9c1b51eSKate Stone load_script_old_value = 207b9c1b51eSKate Stone target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 20884a53dfbSEnrico Granata } 20997206d57SZachary Turner Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value)); 210b9c1b51eSKate Stone if (error.Success()) { 21184a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 212a8ea5955SJonas Devlieghere if (property_path == g_debugger_properties[ePropertyPrompt].name) { 213514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 2144b3c0fd5SJonas Devlieghere std::string str = lldb_private::ansi::FormatAnsiTerminalCodes( 215b9c1b51eSKate Stone new_prompt, GetUseColor()); 216c3ce7f27SMichael Sartain if (str.length()) 217771ef6d4SMalcolm Parsons new_prompt = str; 21844d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 219a8f3ae7cSJonas Devlieghere auto bytes = std::make_unique<EventDataBytes>(new_prompt); 2202f3df613SZachary Turner auto prompt_change_event_sp = std::make_shared<Event>( 2212f3df613SZachary Turner CommandInterpreter::eBroadcastBitResetPrompt, bytes.release()); 2224c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp); 223a8ea5955SJonas Devlieghere } else if (property_path == g_debugger_properties[ePropertyUseColor].name) { 224b9c1b51eSKate Stone // use-color changed. Ping the prompt so it can reset the ansi terminal 225b9c1b51eSKate Stone // codes. 226c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 227acae69d0SEmre Kultursay } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) { 228acae69d0SEmre Kultursay // use-source-cache changed. Wipe out the cache contents if it was disabled. 229acae69d0SEmre Kultursay if (!GetUseSourceCache()) { 230acae69d0SEmre Kultursay m_source_file_cache.Clear(); 231acae69d0SEmre Kultursay } 232b9c1b51eSKate Stone } else if (is_load_script && target_sp && 233b9c1b51eSKate Stone load_script_old_value == eLoadScriptFromSymFileWarn) { 234b9c1b51eSKate Stone if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == 235b9c1b51eSKate Stone eLoadScriptFromSymFileTrue) { 23697206d57SZachary Turner std::list<Status> errors; 2379730339bSEnrico Granata StreamString feedback_stream; 238b9c1b51eSKate Stone if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { 2397ca15ba7SLawrence D'Anna Stream &s = GetErrorStream(); 240b9c1b51eSKate Stone for (auto error : errors) { 2417ca15ba7SLawrence D'Anna s.Printf("%s\n", error.AsCString()); 24284a53dfbSEnrico Granata } 2439730339bSEnrico Granata if (feedback_stream.GetSize()) 2447ca15ba7SLawrence D'Anna s.PutCString(feedback_stream.GetString()); 24584a53dfbSEnrico Granata } 24684a53dfbSEnrico Granata } 247ebdc1ac0SEnrico Granata } 2484c05410fSGreg Clayton } 2494c05410fSGreg Clayton return error; 2504c05410fSGreg Clayton } 2514c05410fSGreg Clayton 252b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const { 25367cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 254b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 255a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 25667cc0636SGreg Clayton } 25767cc0636SGreg Clayton 258b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { 259aff1b357SJason Molenda const uint32_t idx = ePropertyDisassemblyFormat; 260df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 261aff1b357SJason Molenda } 262aff1b357SJason Molenda 263b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const { 26467cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 265df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 26667cc0636SGreg Clayton } 26767cc0636SGreg Clayton 2687f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { 2697f1c1211SPavel Labath const uint32_t idx = ePropertyFrameFormatUnique; 2707f1c1211SPavel Labath return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 2717f1c1211SPavel Labath } 2727f1c1211SPavel Labath 273b889ef42SMed Ismail Bennani uint32_t Debugger::GetStopDisassemblyMaxSize() const { 274b889ef42SMed Ismail Bennani const uint32_t idx = ePropertyStopDisassemblyMaxSize; 275b889ef42SMed Ismail Bennani return m_collection_sp->GetPropertyAtIndexAsUInt64( 276b889ef42SMed Ismail Bennani nullptr, idx, g_debugger_properties[idx].default_uint_value); 277b889ef42SMed Ismail Bennani } 278b889ef42SMed Ismail Bennani 279b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const { 28067cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 281b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 282a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 28367cc0636SGreg Clayton } 28467cc0636SGreg Clayton 285514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const { 28667cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 287b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsString( 288a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_cstr_value); 28967cc0636SGreg Clayton } 29067cc0636SGreg Clayton 291514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) { 29267cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 293df370550SEugene Zelenko m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); 294514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 295b9c1b51eSKate Stone std::string str = 2964b3c0fd5SJonas Devlieghere lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); 297c3ce7f27SMichael Sartain if (str.length()) 298771ef6d4SMalcolm Parsons new_prompt = str; 29944d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 30067cc0636SGreg Clayton } 30167cc0636SGreg Clayton 3029e046f02SJonas Devlieghere llvm::StringRef Debugger::GetReproducerPath() const { 3039e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 3049e046f02SJonas Devlieghere return r.GetReproducerPath().GetCString(); 3059e046f02SJonas Devlieghere } 3069e046f02SJonas Devlieghere 307b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const { 30867cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 309df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 31067cc0636SGreg Clayton } 31167cc0636SGreg Clayton 3126a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { 3136a9767c7SJim Ingham const uint32_t idx = ePropertyThreadStopFormat; 3146a9767c7SJim Ingham return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 3156a9767c7SJim Ingham } 3166a9767c7SJim Ingham 317b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const { 31867cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 319b9c1b51eSKate Stone return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( 320a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 32167cc0636SGreg Clayton } 32267cc0636SGreg Clayton 323b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { 32467cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 325b9c1b51eSKate Stone return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, 326b9c1b51eSKate Stone script_lang); 32767cc0636SGreg Clayton } 32867cc0636SGreg Clayton 32946a28a95SJonas Devlieghere lldb::LanguageType Debugger::GetREPLLanguage() const { 33046a28a95SJonas Devlieghere const uint32_t idx = ePropertyREPLLanguage; 33146a28a95SJonas Devlieghere OptionValueLanguage *value = 33246a28a95SJonas Devlieghere m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, idx); 33346a28a95SJonas Devlieghere if (value) 33446a28a95SJonas Devlieghere return value->GetCurrentValue(); 33546a28a95SJonas Devlieghere return LanguageType(); 33646a28a95SJonas Devlieghere } 33746a28a95SJonas Devlieghere 33846a28a95SJonas Devlieghere bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) { 33946a28a95SJonas Devlieghere const uint32_t idx = ePropertyREPLLanguage; 34046a28a95SJonas Devlieghere return m_collection_sp->SetPropertyAtIndexAsLanguage(nullptr, idx, repl_lang); 34146a28a95SJonas Devlieghere } 34246a28a95SJonas Devlieghere 343b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const { 34467cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 345b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 346a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 34767cc0636SGreg Clayton } 34867cc0636SGreg Clayton 349b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) { 350d9166ad2SFred Riss if (auto handler_sp = m_io_handler_stack.Top()) 351d9166ad2SFred Riss handler_sp->TerminalSizeChanged(); 352d9166ad2SFred Riss 35367cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 354df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); 35567cc0636SGreg Clayton } 35667cc0636SGreg Clayton 357b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const { 35867cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 359b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 360a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 36167cc0636SGreg Clayton } 36267cc0636SGreg Clayton 363b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) { 36467cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 365df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 36667cc0636SGreg Clayton } 36767cc0636SGreg Clayton 368b9c1b51eSKate Stone bool Debugger::GetUseColor() const { 369c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 370b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 371a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 372c3ce7f27SMichael Sartain } 373c3ce7f27SMichael Sartain 374b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) { 375c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 376df370550SEugene Zelenko bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 377c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 378c3ce7f27SMichael Sartain return ret; 379c3ce7f27SMichael Sartain } 380c3ce7f27SMichael Sartain 381de9e8502SShu Anzai bool Debugger::GetUseAutosuggestion() const { 382de9e8502SShu Anzai const uint32_t idx = ePropertyShowAutosuggestion; 383de9e8502SShu Anzai return m_collection_sp->GetPropertyAtIndexAsBoolean( 384de9e8502SShu Anzai nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 385de9e8502SShu Anzai } 386de9e8502SShu Anzai 387*080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const { 388*080635efSJonas Devlieghere const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix; 389*080635efSJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 390*080635efSJonas Devlieghere } 391*080635efSJonas Devlieghere 392*080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const { 393*080635efSJonas Devlieghere const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix; 394*080635efSJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 395*080635efSJonas Devlieghere } 396*080635efSJonas Devlieghere 397acae69d0SEmre Kultursay bool Debugger::GetUseSourceCache() const { 398acae69d0SEmre Kultursay const uint32_t idx = ePropertyUseSourceCache; 399acae69d0SEmre Kultursay return m_collection_sp->GetPropertyAtIndexAsBoolean( 400acae69d0SEmre Kultursay nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 401acae69d0SEmre Kultursay } 402acae69d0SEmre Kultursay 403acae69d0SEmre Kultursay bool Debugger::SetUseSourceCache(bool b) { 404acae69d0SEmre Kultursay const uint32_t idx = ePropertyUseSourceCache; 405acae69d0SEmre Kultursay bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 406acae69d0SEmre Kultursay if (!ret) { 407acae69d0SEmre Kultursay m_source_file_cache.Clear(); 408acae69d0SEmre Kultursay } 409acae69d0SEmre Kultursay return ret; 410acae69d0SEmre Kultursay } 411566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const { 412566afa0aSRaphael Isemann const uint32_t idx = ePropertyHighlightSource; 413566afa0aSRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsBoolean( 414a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 415566afa0aSRaphael Isemann } 416566afa0aSRaphael Isemann 4179666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const { 4189666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumn; 4199666ba75STodd Fiala return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( 420a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4219666ba75STodd Fiala } 4229666ba75STodd Fiala 42320786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const { 4249666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiPrefix; 42520786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4269666ba75STodd Fiala } 4279666ba75STodd Fiala 42820786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const { 4299666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiSuffix; 43020786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4319666ba75STodd Fiala } 4329666ba75STodd Fiala 433841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const { 434841be985SJonas Devlieghere const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix; 435841be985SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 436841be985SJonas Devlieghere } 437841be985SJonas Devlieghere 438841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const { 439841be985SJonas Devlieghere const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix; 440841be985SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 441841be985SJonas Devlieghere } 442841be985SJonas Devlieghere 443b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const { 444b9c1b51eSKate Stone const uint32_t idx = 445b9c1b51eSKate Stone before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 446b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 447a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 44867cc0636SGreg Clayton } 44967cc0636SGreg Clayton 450b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { 45167cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 452b9c1b51eSKate Stone return (Debugger::StopDisassemblyType) 453b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsEnumeration( 454a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 45567cc0636SGreg Clayton } 45667cc0636SGreg Clayton 457b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const { 45867cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 459b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 460a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 46167cc0636SGreg Clayton } 462e372b98dSGreg Clayton 463b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const { 46490a8db30SEnrico Granata const uint32_t idx = ePropertyAutoOneLineSummaries; 465df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 466ebdc1ac0SEnrico Granata } 467553fad5cSEnrico Granata 468b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const { 469ebdc1ac0SEnrico Granata const uint32_t idx = ePropertyEscapeNonPrintables; 470df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 471553fad5cSEnrico Granata } 472553fad5cSEnrico Granata 473b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const { 4746681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 475df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4766681041dSSean Callanan } 4776681041dSSean Callanan 478b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) { 4796681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 480df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4816681041dSSean Callanan } 4826681041dSSean Callanan 483b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const { 4846681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 485df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4866681041dSSean Callanan } 4876681041dSSean Callanan 488b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) { 4896681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 490df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4916681041dSSean Callanan } 4926681041dSSean Callanan 493b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const { 4946681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 495b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 496a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4976681041dSSean Callanan } 4986681041dSSean Callanan 499b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) { 5006681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 501df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); 5026681041dSSean Callanan } 5036681041dSSean Callanan 5041b654882SGreg Clayton #pragma mark Debugger 5051b654882SGreg Clayton 50667cc0636SGreg Clayton // const DebuggerPropertiesSP & 50767cc0636SGreg Clayton // Debugger::GetSettings() const 50867cc0636SGreg Clayton //{ 50967cc0636SGreg Clayton // return m_properties_sp; 51067cc0636SGreg Clayton //} 51167cc0636SGreg Clayton // 51299d0faf2SGreg Clayton 513b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) { 514b9c1b51eSKate Stone assert(g_debugger_list_ptr == nullptr && 515b9c1b51eSKate Stone "Debugger::Initialize called more than once!"); 5166c42e063SGreg Clayton g_debugger_list_mutex_ptr = new std::recursive_mutex(); 5176c42e063SGreg Clayton g_debugger_list_ptr = new DebuggerList(); 5185fb8f797SGreg Clayton g_load_plugin_callback = load_plugin_callback; 51999d0faf2SGreg Clayton } 52030fdc8d8SChris Lattner 521b9c1b51eSKate Stone void Debugger::Terminate() { 522b9c1b51eSKate Stone assert(g_debugger_list_ptr && 523b9c1b51eSKate Stone "Debugger::Terminate called without a matching Debugger::Initialize!"); 524e6e2bb38SZachary Turner 525b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 52695af9d88SQuinn Pham // Clear our global list of debugger objects 5276c42e063SGreg Clayton { 5286c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 5296c42e063SGreg Clayton for (const auto &debugger : *g_debugger_list_ptr) 530f3cd1819SOleksiy Vyalov debugger->Clear(); 5316c42e063SGreg Clayton g_debugger_list_ptr->clear(); 5326c42e063SGreg Clayton } 5336c42e063SGreg Clayton } 53430fdc8d8SChris Lattner } 53530fdc8d8SChris Lattner 536b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); } 53720bd37f7SCaroline Tice 538b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); } 53920bd37f7SCaroline Tice 54097206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) { 541b9c1b51eSKate Stone if (g_load_plugin_callback) { 542b9c1b51eSKate Stone llvm::sys::DynamicLibrary dynlib = 543b9c1b51eSKate Stone g_load_plugin_callback(shared_from_this(), spec, error); 544b9c1b51eSKate Stone if (dynlib.isValid()) { 54558a559c0SZachary Turner m_loaded_plugins.push_back(dynlib); 54621dfcd9dSEnrico Granata return true; 54721dfcd9dSEnrico Granata } 548b9c1b51eSKate Stone } else { 54905097246SAdrian Prantl // The g_load_plugin_callback is registered in SBDebugger::Initialize() and 55005097246SAdrian Prantl // if the public API layer isn't available (code is linking against all of 55105097246SAdrian Prantl // the internal LLDB static libraries), then we can't load plugins 5525fb8f797SGreg Clayton error.SetErrorString("Public API layer is not available"); 5535fb8f797SGreg Clayton } 55421dfcd9dSEnrico Granata return false; 55521dfcd9dSEnrico Granata } 55621dfcd9dSEnrico Granata 55735e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult 5587d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, 55935e4c84cSJonas Devlieghere llvm::StringRef path) { 56097206d57SZachary Turner Status error; 56121dfcd9dSEnrico Granata 562ad8d48f9SJonas Devlieghere static ConstString g_dylibext(".dylib"); 563ad8d48f9SJonas Devlieghere static ConstString g_solibext(".so"); 56421dfcd9dSEnrico Granata 56521dfcd9dSEnrico Granata if (!baton) 56635e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultQuit; 56721dfcd9dSEnrico Granata 56821dfcd9dSEnrico Granata Debugger *debugger = (Debugger *)baton; 56921dfcd9dSEnrico Granata 5707d86ee5aSZachary Turner namespace fs = llvm::sys::fs; 57105097246SAdrian Prantl // If we have a regular file, a symbolic link or unknown file type, try and 57205097246SAdrian Prantl // process the file. We must handle unknown as sometimes the directory 57321dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 57421dfcd9dSEnrico Granata // file type information. 5757d86ee5aSZachary Turner if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file || 5767d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 5778f3be7a3SJonas Devlieghere FileSpec plugin_file_spec(path); 5788f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(plugin_file_spec); 57921dfcd9dSEnrico Granata 5803cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 581b9c1b51eSKate Stone plugin_file_spec.GetFileNameExtension() != g_solibext) { 58235e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 5833cf443ddSMichael Sartain } 58421dfcd9dSEnrico Granata 58597206d57SZachary Turner Status plugin_load_error; 586e743c782SEnrico Granata debugger->LoadPlugin(plugin_file_spec, plugin_load_error); 58721dfcd9dSEnrico Granata 58835e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 5897d86ee5aSZachary Turner } else if (ft == fs::file_type::directory_file || 5907d86ee5aSZachary Turner ft == fs::file_type::symlink_file || 5917d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 59205097246SAdrian Prantl // Try and recurse into anything that a directory or symbolic link. We must 59305097246SAdrian Prantl // also do this for unknown as sometimes the directory enumeration might be 59405097246SAdrian Prantl // enumerating a file system that doesn't have correct file type 59521dfcd9dSEnrico Granata // information. 59635e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultEnter; 59721dfcd9dSEnrico Granata } 59821dfcd9dSEnrico Granata 59935e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 60021dfcd9dSEnrico Granata } 60121dfcd9dSEnrico Granata 602b9c1b51eSKate Stone void Debugger::InstanceInitialize() { 60321dfcd9dSEnrico Granata const bool find_directories = true; 60421dfcd9dSEnrico Granata const bool find_files = true; 60521dfcd9dSEnrico Granata const bool find_other = true; 60621dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 60760f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) { 608dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 609dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 61035e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 61135e4c84cSJonas Devlieghere find_files, find_other, 61235e4c84cSJonas Devlieghere LoadPluginCallback, this); 61321dfcd9dSEnrico Granata } 61421dfcd9dSEnrico Granata } 61521dfcd9dSEnrico Granata 61660f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) { 617dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 618dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 61935e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 62035e4c84cSJonas Devlieghere find_files, find_other, 62135e4c84cSJonas Devlieghere LoadPluginCallback, this); 62221dfcd9dSEnrico Granata } 62321dfcd9dSEnrico Granata } 624e8cd0c98SGreg Clayton 625e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize(*this); 62621dfcd9dSEnrico Granata } 62721dfcd9dSEnrico Granata 628b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, 629b9c1b51eSKate Stone void *baton) { 630228063cdSJim Ingham DebuggerSP debugger_sp(new Debugger(log_callback, baton)); 631b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6326c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6336c42e063SGreg Clayton g_debugger_list_ptr->push_back(debugger_sp); 6346611103cSGreg Clayton } 63521dfcd9dSEnrico Granata debugger_sp->InstanceInitialize(); 6366611103cSGreg Clayton return debugger_sp; 6376611103cSGreg Clayton } 6386611103cSGreg Clayton 639b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) { 640df370550SEugene Zelenko if (!debugger_sp) 641e02657b1SCaroline Tice return; 642e02657b1SCaroline Tice 643d6b64612SMed Ismail Bennani CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter(); 644d6b64612SMed Ismail Bennani 645d6b64612SMed Ismail Bennani if (cmd_interpreter.GetSaveSessionOnQuit()) { 646d6b64612SMed Ismail Bennani CommandReturnObject result(debugger_sp->GetUseColor()); 647d6b64612SMed Ismail Bennani cmd_interpreter.SaveTranscript(result); 648d6b64612SMed Ismail Bennani if (result.Succeeded()) 649d6b64612SMed Ismail Bennani debugger_sp->GetOutputStream() << result.GetOutputData() << '\n'; 650d6b64612SMed Ismail Bennani else 651d6b64612SMed Ismail Bennani debugger_sp->GetErrorStream() << result.GetErrorData() << '\n'; 652d6b64612SMed Ismail Bennani } 653d6b64612SMed Ismail Bennani 6548314c525SJim Ingham debugger_sp->Clear(); 6558314c525SJim Ingham 656b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6576c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6586c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 659b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 660b9c1b51eSKate Stone if ((*pos).get() == debugger_sp.get()) { 6616c42e063SGreg Clayton g_debugger_list_ptr->erase(pos); 662e02657b1SCaroline Tice return; 663e02657b1SCaroline Tice } 664e02657b1SCaroline Tice } 665e02657b1SCaroline Tice } 666c15f55e2SGreg Clayton } 667e02657b1SCaroline Tice 668e063ecccSJonas Devlieghere DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { 6694d122c40SGreg Clayton DebuggerSP debugger_sp; 670b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6716c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6726c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 673b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 674b9c1b51eSKate Stone if ((*pos)->m_instance_name == instance_name) { 6756920b52bSGreg Clayton debugger_sp = *pos; 6766920b52bSGreg Clayton break; 6776920b52bSGreg Clayton } 6786920b52bSGreg Clayton } 6796920b52bSGreg Clayton } 6803df9a8dfSCaroline Tice return debugger_sp; 6813df9a8dfSCaroline Tice } 6826611103cSGreg Clayton 683b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) { 6844d122c40SGreg Clayton TargetSP target_sp; 685b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6866c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6876c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 688b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 6896611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid); 6906611103cSGreg Clayton if (target_sp) 6916611103cSGreg Clayton break; 6926611103cSGreg Clayton } 693c15f55e2SGreg Clayton } 6946611103cSGreg Clayton return target_sp; 6956611103cSGreg Clayton } 6966611103cSGreg Clayton 697b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) { 698e4e45924SGreg Clayton TargetSP target_sp; 699b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 7006c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 7016c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 702b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 703e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process); 704e4e45924SGreg Clayton if (target_sp) 705e4e45924SGreg Clayton break; 706e4e45924SGreg Clayton } 707c15f55e2SGreg Clayton } 708e4e45924SGreg Clayton return target_sp; 709e4e45924SGreg Clayton } 710e4e45924SGreg Clayton 711e122877fSGreg Clayton ConstString Debugger::GetStaticBroadcasterClass() { 712e122877fSGreg Clayton static ConstString class_name("lldb.debugger"); 713e122877fSGreg Clayton return class_name; 714e122877fSGreg Clayton } 715e122877fSGreg Clayton 716b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) 717b9c1b51eSKate Stone : UserID(g_unique_id++), 7182f3df613SZachary Turner Properties(std::make_shared<OptionValueProperties>()), 719f913fd6eSLawrence D'Anna m_input_file_sp(std::make_shared<NativeFile>(stdin, false)), 7207ca15ba7SLawrence D'Anna m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)), 7217ca15ba7SLawrence D'Anna m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)), 722d77c2e09SJonas Devlieghere m_input_recorder(nullptr), 723583bbb1dSJim Ingham m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), 724b9c1b51eSKate Stone m_terminal_state(), m_target_list(*this), m_platform_list(), 725583bbb1dSJim Ingham m_listener_sp(Listener::MakeListener("lldb.Debugger")), 726d5b44036SJonas Devlieghere m_source_manager_up(), m_source_file_cache(), 727f20dd1d5SJonas Devlieghere m_command_interpreter_up( 728a8f3ae7cSJonas Devlieghere std::make_unique<CommandInterpreter>(*this, false)), 7297ce2de2cSJonas Devlieghere m_io_handler_stack(), m_instance_name(), m_loaded_plugins(), 730bbf70c04SJonas Devlieghere m_event_handler_thread(), m_io_handler_thread(), 7314329fe42SGreg Clayton m_sync_broadcaster(nullptr, "lldb.debugger.sync"), 732e122877fSGreg Clayton m_broadcaster(m_broadcaster_manager_sp, 733e122877fSGreg Clayton GetStaticBroadcasterClass().AsCString()), 734b9c1b51eSKate Stone m_forward_listener_sp(), m_clear_once() { 735db203e02SRaphael Isemann m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str()); 736228063cdSJim Ingham if (log_callback) 7372f3df613SZachary Turner m_log_callback_stream_sp = 7382f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 739d5b44036SJonas Devlieghere m_command_interpreter_up->Initialize(); 740ded470d3SGreg Clayton // Always add our default platform to the platform list 741615eb7e6SGreg Clayton PlatformSP default_platform_sp(Platform::GetHostPlatform()); 742df370550SEugene Zelenko assert(default_platform_sp); 743ded470d3SGreg Clayton m_platform_list.Append(default_platform_sp, true); 74467cc0636SGreg Clayton 74516e5a347SVedant Kumar // Create the dummy target. 74616e5a347SVedant Kumar { 74716e5a347SVedant Kumar ArchSpec arch(Target::GetDefaultArchitecture()); 74816e5a347SVedant Kumar if (!arch.IsValid()) 74916e5a347SVedant Kumar arch = HostInfo::GetArchitecture(); 75016e5a347SVedant Kumar assert(arch.IsValid() && "No valid default or host archspec"); 75116e5a347SVedant Kumar const bool is_dummy_target = true; 75216e5a347SVedant Kumar m_dummy_target_sp.reset( 75316e5a347SVedant Kumar new Target(*this, arch, default_platform_sp, is_dummy_target)); 75416e5a347SVedant Kumar } 755d43d912bSRaphael Isemann assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?"); 756d43d912bSRaphael Isemann 757a8ea5955SJonas Devlieghere m_collection_sp->Initialize(g_debugger_properties); 758b9c1b51eSKate Stone m_collection_sp->AppendProperty( 759b9c1b51eSKate Stone ConstString("target"), 760b9c1b51eSKate Stone ConstString("Settings specify to debugging targets."), true, 7613d7161e3SPavel Labath Target::GetGlobalProperties().GetValueProperties()); 762b9c1b51eSKate Stone m_collection_sp->AppendProperty( 763b9c1b51eSKate Stone ConstString("platform"), ConstString("Platform settings."), true, 7643d7161e3SPavel Labath Platform::GetGlobalPlatformProperties().GetValueProperties()); 765235354beSAdrian Prantl m_collection_sp->AppendProperty( 7663cd29bcfSAdrian Prantl ConstString("symbols"), ConstString("Symbol lookup and cache settings."), 7673cd29bcfSAdrian Prantl true, ModuleList::GetGlobalModuleListProperties().GetValueProperties()); 768d5b44036SJonas Devlieghere if (m_command_interpreter_up) { 769b9c1b51eSKate Stone m_collection_sp->AppendProperty( 770b9c1b51eSKate Stone ConstString("interpreter"), 771754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 772d5b44036SJonas Devlieghere true, m_command_interpreter_up->GetValueProperties()); 773754a9369SGreg Clayton } 774b9c1b51eSKate Stone OptionValueSInt64 *term_width = 775b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64( 776b9c1b51eSKate Stone nullptr, ePropertyTerminalWidth); 77767cc0636SGreg Clayton term_width->SetMinimumValue(10); 77867cc0636SGreg Clayton term_width->SetMaximumValue(1024); 779c3ce7f27SMichael Sartain 780c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 781c3ce7f27SMichael Sartain const char *term = getenv("TERM"); 782c3ce7f27SMichael Sartain if (term && !strcmp(term, "dumb")) 783c3ce7f27SMichael Sartain SetUseColor(false); 784eca9ce14SRaphael Isemann // Turn off use-color if we don't write to a terminal with color support. 7857ca15ba7SLawrence D'Anna if (!GetOutputFile().GetIsTerminalWithColors()) 786eca9ce14SRaphael Isemann SetUseColor(false); 7878aa23614SDavid Bolvansky 7888aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) 7898aa23614SDavid Bolvansky // Enabling use of ANSI color codes because LLDB is using them to highlight 7908aa23614SDavid Bolvansky // text. 7918aa23614SDavid Bolvansky llvm::sys::Process::UseANSIEscapeCodes(true); 7928aa23614SDavid Bolvansky #endif 79330fdc8d8SChris Lattner } 79430fdc8d8SChris Lattner 795b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); } 7968314c525SJim Ingham 797b9c1b51eSKate Stone void Debugger::Clear() { 79805097246SAdrian Prantl // Make sure we call this function only once. With the C++ global destructor 79905097246SAdrian Prantl // chain having a list of debuggers and with code that can be running on 80005097246SAdrian Prantl // other threads, we need to ensure this doesn't happen multiple times. 8014329fe42SGreg Clayton // 8024329fe42SGreg Clayton // The following functions call Debugger::Clear(): 8034329fe42SGreg Clayton // Debugger::~Debugger(); 8044329fe42SGreg Clayton // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp); 8054329fe42SGreg Clayton // static void Debugger::Terminate(); 806c5f28e2aSKamil Rytarowski llvm::call_once(m_clear_once, [this]() { 80744d93782SGreg Clayton ClearIOHandlers(); 80844d93782SGreg Clayton StopIOHandlerThread(); 80944d93782SGreg Clayton StopEventHandlerThread(); 810583bbb1dSJim Ingham m_listener_sp->Clear(); 811de448c0aSJonas Devlieghere for (TargetSP target_sp : m_target_list.Targets()) { 812b9c1b51eSKate Stone if (target_sp) { 813de448c0aSJonas Devlieghere if (ProcessSP process_sp = target_sp->GetProcessSP()) 8141fd07059SJim Ingham process_sp->Finalize(); 815ccbc08e6SGreg Clayton target_sp->Destroy(); 8166611103cSGreg Clayton } 81730fdc8d8SChris Lattner } 818583bbb1dSJim Ingham m_broadcaster_manager_sp->Clear(); 81930fdc8d8SChris Lattner 820b9c1b51eSKate Stone // Close the input file _before_ we close the input read communications 82105097246SAdrian Prantl // class as it does NOT own the input file, our m_input_file does. 822c5917d9aSJim Ingham m_terminal_state.Clear(); 8237ca15ba7SLawrence D'Anna GetInputFile().Close(); 8240c4129f2SGreg Clayton 825d5b44036SJonas Devlieghere m_command_interpreter_up->Clear(); 8264329fe42SGreg Clayton }); 8278314c525SJim Ingham } 82830fdc8d8SChris Lattner 829b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const { 83044d93782SGreg Clayton // return m_input_comm.GetCloseOnEOF(); 83144d93782SGreg Clayton return false; 832fc3f027dSGreg Clayton } 833fc3f027dSGreg Clayton 834b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) { 83544d93782SGreg Clayton // m_input_comm.SetCloseOnEOF(b); 836fc3f027dSGreg Clayton } 837fc3f027dSGreg Clayton 838b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() { 839d5b44036SJonas Devlieghere return !m_command_interpreter_up->GetSynchronous(); 84030fdc8d8SChris Lattner } 84130fdc8d8SChris Lattner 842b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) { 843d5b44036SJonas Devlieghere m_command_interpreter_up->SetSynchronous(!async_execution); 84430fdc8d8SChris Lattner } 84530fdc8d8SChris Lattner 846d77c2e09SJonas Devlieghere repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; } 847d77c2e09SJonas Devlieghere 848f23b829aSLevon Ter-Grigoryan static inline int OpenPipe(int fds[2], std::size_t size) { 849f23b829aSLevon Ter-Grigoryan #ifdef _WIN32 850f23b829aSLevon Ter-Grigoryan return _pipe(fds, size, O_BINARY); 851f23b829aSLevon Ter-Grigoryan #else 852f23b829aSLevon Ter-Grigoryan (void)size; 853f23b829aSLevon Ter-Grigoryan return pipe(fds); 854f23b829aSLevon Ter-Grigoryan #endif 855f23b829aSLevon Ter-Grigoryan } 856f23b829aSLevon Ter-Grigoryan 857f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputString(const char *data) { 858f23b829aSLevon Ter-Grigoryan Status result; 859f23b829aSLevon Ter-Grigoryan enum PIPES { READ, WRITE }; // Indexes for the read and write fds 860f23b829aSLevon Ter-Grigoryan int fds[2] = {-1, -1}; 861f23b829aSLevon Ter-Grigoryan 862f23b829aSLevon Ter-Grigoryan if (data == nullptr) { 863f23b829aSLevon Ter-Grigoryan result.SetErrorString("String data is null"); 864f23b829aSLevon Ter-Grigoryan return result; 865f23b829aSLevon Ter-Grigoryan } 866f23b829aSLevon Ter-Grigoryan 867f23b829aSLevon Ter-Grigoryan size_t size = strlen(data); 868f23b829aSLevon Ter-Grigoryan if (size == 0) { 869f23b829aSLevon Ter-Grigoryan result.SetErrorString("String data is empty"); 870f23b829aSLevon Ter-Grigoryan return result; 871f23b829aSLevon Ter-Grigoryan } 872f23b829aSLevon Ter-Grigoryan 873f23b829aSLevon Ter-Grigoryan if (OpenPipe(fds, size) != 0) { 874f23b829aSLevon Ter-Grigoryan result.SetErrorString( 875f23b829aSLevon Ter-Grigoryan "can't create pipe file descriptors for LLDB commands"); 876f23b829aSLevon Ter-Grigoryan return result; 877f23b829aSLevon Ter-Grigoryan } 878f23b829aSLevon Ter-Grigoryan 879f23b829aSLevon Ter-Grigoryan write(fds[WRITE], data, size); 880f23b829aSLevon Ter-Grigoryan // Close the write end of the pipe, so that the command interpreter will exit 881f23b829aSLevon Ter-Grigoryan // when it consumes all the data. 882f23b829aSLevon Ter-Grigoryan llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 883f23b829aSLevon Ter-Grigoryan 884f23b829aSLevon Ter-Grigoryan // Open the read file descriptor as a FILE * that we can return as an input 885f23b829aSLevon Ter-Grigoryan // handle. 886f23b829aSLevon Ter-Grigoryan FILE *commands_file = fdopen(fds[READ], "rb"); 887f23b829aSLevon Ter-Grigoryan if (commands_file == nullptr) { 888f23b829aSLevon Ter-Grigoryan result.SetErrorStringWithFormat("fdopen(%i, \"rb\") failed (errno = %i) " 889f23b829aSLevon Ter-Grigoryan "when trying to open LLDB commands pipe", 890f23b829aSLevon Ter-Grigoryan fds[READ], errno); 891f23b829aSLevon Ter-Grigoryan llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 892f23b829aSLevon Ter-Grigoryan return result; 893f23b829aSLevon Ter-Grigoryan } 894f23b829aSLevon Ter-Grigoryan 895f23b829aSLevon Ter-Grigoryan return SetInputFile( 896f23b829aSLevon Ter-Grigoryan (FileSP)std::make_shared<NativeFile>(commands_file, true)); 897f23b829aSLevon Ter-Grigoryan } 898f23b829aSLevon Ter-Grigoryan 899f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputFile(FileSP file_sp) { 900f23b829aSLevon Ter-Grigoryan Status error; 901f23b829aSLevon Ter-Grigoryan repro::DataRecorder *recorder = nullptr; 902f23b829aSLevon Ter-Grigoryan if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) 903f23b829aSLevon Ter-Grigoryan recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder(); 904f23b829aSLevon Ter-Grigoryan 905f23b829aSLevon Ter-Grigoryan static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader = 906f23b829aSLevon Ter-Grigoryan repro::MultiLoader<repro::CommandProvider>::Create( 907f23b829aSLevon Ter-Grigoryan repro::Reproducer::Instance().GetLoader()); 908f23b829aSLevon Ter-Grigoryan if (loader) { 909f23b829aSLevon Ter-Grigoryan llvm::Optional<std::string> nextfile = loader->GetNextFile(); 910f23b829aSLevon Ter-Grigoryan FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r") 911f23b829aSLevon Ter-Grigoryan : nullptr; 912f23b829aSLevon Ter-Grigoryan // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the 913f23b829aSLevon Ter-Grigoryan // reproducer somehow if fh is NULL? 914f23b829aSLevon Ter-Grigoryan if (fh) { 915f23b829aSLevon Ter-Grigoryan file_sp = std::make_shared<NativeFile>(fh, true); 916f23b829aSLevon Ter-Grigoryan } 917f23b829aSLevon Ter-Grigoryan } 918f23b829aSLevon Ter-Grigoryan 919f23b829aSLevon Ter-Grigoryan if (!file_sp || !file_sp->IsValid()) { 920f23b829aSLevon Ter-Grigoryan error.SetErrorString("invalid file"); 921f23b829aSLevon Ter-Grigoryan return error; 922f23b829aSLevon Ter-Grigoryan } 923f23b829aSLevon Ter-Grigoryan 924f23b829aSLevon Ter-Grigoryan SetInputFile(file_sp, recorder); 925f23b829aSLevon Ter-Grigoryan return error; 926f23b829aSLevon Ter-Grigoryan } 927f23b829aSLevon Ter-Grigoryan 92896898eb6SLawrence D'Anna void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) { 92996898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 930d77c2e09SJonas Devlieghere m_input_recorder = recorder; 931c4701c9cSJonas Devlieghere m_input_file_sp = std::move(file_sp); 93205097246SAdrian Prantl // Save away the terminal state if that is relevant, so that we can restore 93305097246SAdrian Prantl // it in RestoreInputState. 934c5917d9aSJim Ingham SaveInputTerminalState(); 93530fdc8d8SChris Lattner } 93630fdc8d8SChris Lattner 93796898eb6SLawrence D'Anna void Debugger::SetOutputFile(FileSP file_sp) { 93896898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 9397ca15ba7SLawrence D'Anna m_output_stream_sp = std::make_shared<StreamFile>(file_sp); 94030fdc8d8SChris Lattner } 94130fdc8d8SChris Lattner 94296898eb6SLawrence D'Anna void Debugger::SetErrorFile(FileSP file_sp) { 94396898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 9447ca15ba7SLawrence D'Anna m_error_stream_sp = std::make_shared<StreamFile>(file_sp); 94530fdc8d8SChris Lattner } 94630fdc8d8SChris Lattner 947b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() { 9487ca15ba7SLawrence D'Anna int fd = GetInputFile().GetDescriptor(); 9497ca15ba7SLawrence D'Anna if (fd != File::kInvalidDescriptor) 9507ca15ba7SLawrence D'Anna m_terminal_state.Save(fd, true); 95144d93782SGreg Clayton } 952c5917d9aSJim Ingham 953b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } 954c5917d9aSJim Ingham 955b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() { 956a39bcbcaSTatyana Krasnukha bool adopt_selected = true; 957a39bcbcaSTatyana Krasnukha ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected); 958a39bcbcaSTatyana Krasnukha return ExecutionContext(exe_ctx_ref); 95930fdc8d8SChris Lattner } 96030fdc8d8SChris Lattner 961b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() { 9627ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 9637ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 964efed6131SCaroline Tice if (reader_sp) 96544d93782SGreg Clayton reader_sp->Interrupt(); 966efed6131SCaroline Tice } 967efed6131SCaroline Tice 968b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() { 9697ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 9707ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 971efed6131SCaroline Tice if (reader_sp) 97244d93782SGreg Clayton reader_sp->GotEOF(); 973efed6131SCaroline Tice } 974efed6131SCaroline Tice 975b9c1b51eSKate Stone void Debugger::ClearIOHandlers() { 976b9c1b51eSKate Stone // The bottom input reader should be the main debugger input reader. We do 977b9c1b51eSKate Stone // not want to close that one here. 9787ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 9797ce2de2cSJonas Devlieghere while (m_io_handler_stack.GetSize() > 1) { 9807ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 9813d6086f6SCaroline Tice if (reader_sp) 9824446487dSPavel Labath PopIOHandler(reader_sp); 9833d6086f6SCaroline Tice } 9843d6086f6SCaroline Tice } 9853d6086f6SCaroline Tice 9862671df9bSJonas Devlieghere void Debugger::RunIOHandlers() { 98704de24e6SJonas Devlieghere IOHandlerSP reader_sp = m_io_handler_stack.Top(); 988b9c1b51eSKate Stone while (true) { 98930fdc8d8SChris Lattner if (!reader_sp) 99030fdc8d8SChris Lattner break; 99130fdc8d8SChris Lattner 99244d93782SGreg Clayton reader_sp->Run(); 99304de24e6SJonas Devlieghere { 99404de24e6SJonas Devlieghere std::lock_guard<std::recursive_mutex> guard( 99504de24e6SJonas Devlieghere m_io_handler_synchronous_mutex); 99644d93782SGreg Clayton 99744d93782SGreg Clayton // Remove all input readers that are done from the top of the stack 998b9c1b51eSKate Stone while (true) { 9997ce2de2cSJonas Devlieghere IOHandlerSP top_reader_sp = m_io_handler_stack.Top(); 100044d93782SGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 10014446487dSPavel Labath PopIOHandler(top_reader_sp); 100230fdc8d8SChris Lattner else 100330fdc8d8SChris Lattner break; 100430fdc8d8SChris Lattner } 100504de24e6SJonas Devlieghere reader_sp = m_io_handler_stack.Top(); 100604de24e6SJonas Devlieghere } 100730fdc8d8SChris Lattner } 100844d93782SGreg Clayton ClearIOHandlers(); 100944d93782SGreg Clayton } 101030fdc8d8SChris Lattner 101104de24e6SJonas Devlieghere void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) { 101204de24e6SJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex); 101304de24e6SJonas Devlieghere 101404de24e6SJonas Devlieghere PushIOHandler(reader_sp); 101504de24e6SJonas Devlieghere IOHandlerSP top_reader_sp = reader_sp; 101604de24e6SJonas Devlieghere 101704de24e6SJonas Devlieghere while (top_reader_sp) { 101804de24e6SJonas Devlieghere if (!top_reader_sp) 101904de24e6SJonas Devlieghere break; 102004de24e6SJonas Devlieghere 102104de24e6SJonas Devlieghere top_reader_sp->Run(); 102204de24e6SJonas Devlieghere 102304de24e6SJonas Devlieghere // Don't unwind past the starting point. 102404de24e6SJonas Devlieghere if (top_reader_sp.get() == reader_sp.get()) { 102504de24e6SJonas Devlieghere if (PopIOHandler(reader_sp)) 102604de24e6SJonas Devlieghere break; 102704de24e6SJonas Devlieghere } 102804de24e6SJonas Devlieghere 102904de24e6SJonas Devlieghere // If we pushed new IO handlers, pop them if they're done or restart the 103004de24e6SJonas Devlieghere // loop to run them if they're not. 103104de24e6SJonas Devlieghere while (true) { 103204de24e6SJonas Devlieghere top_reader_sp = m_io_handler_stack.Top(); 103304de24e6SJonas Devlieghere if (top_reader_sp && top_reader_sp->GetIsDone()) { 103404de24e6SJonas Devlieghere PopIOHandler(top_reader_sp); 103504de24e6SJonas Devlieghere // Don't unwind past the starting point. 103604de24e6SJonas Devlieghere if (top_reader_sp.get() == reader_sp.get()) 103704de24e6SJonas Devlieghere return; 103804de24e6SJonas Devlieghere } else { 103904de24e6SJonas Devlieghere break; 104004de24e6SJonas Devlieghere } 104104de24e6SJonas Devlieghere } 104204de24e6SJonas Devlieghere } 104304de24e6SJonas Devlieghere } 104404de24e6SJonas Devlieghere 1045b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) { 10467ce2de2cSJonas Devlieghere return m_io_handler_stack.IsTop(reader_sp); 104744d93782SGreg Clayton } 104830fdc8d8SChris Lattner 1049b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, 1050b9c1b51eSKate Stone IOHandler::Type second_top_type) { 10517ce2de2cSJonas Devlieghere return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type); 10526681041dSSean Callanan } 10536681041dSSean Callanan 1054b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { 10557ca15ba7SLawrence D'Anna lldb_private::StreamFile &stream = 10567ca15ba7SLawrence D'Anna is_stdout ? GetOutputStream() : GetErrorStream(); 10577ce2de2cSJonas Devlieghere m_io_handler_stack.PrintAsync(&stream, s, len); 10584446487dSPavel Labath } 105944d93782SGreg Clayton 1060b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { 10617ce2de2cSJonas Devlieghere return m_io_handler_stack.GetTopIOHandlerControlSequence(ch); 106230fdc8d8SChris Lattner } 106330fdc8d8SChris Lattner 1064b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() { 10657ce2de2cSJonas Devlieghere return m_io_handler_stack.GetTopIOHandlerCommandPrefix(); 1066a487aa4cSKate Stone } 1067a487aa4cSKate Stone 1068b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() { 10697ce2de2cSJonas Devlieghere return m_io_handler_stack.GetTopIOHandlerHelpPrologue(); 1070a487aa4cSKate Stone } 1071a487aa4cSKate Stone 10727ce2de2cSJonas Devlieghere bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) { 10737ce2de2cSJonas Devlieghere return PopIOHandler(reader_sp); 10747ce2de2cSJonas Devlieghere } 10757ce2de2cSJonas Devlieghere 10767ce2de2cSJonas Devlieghere void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp, 10777ce2de2cSJonas Devlieghere bool cancel_top_handler) { 10787ce2de2cSJonas Devlieghere PushIOHandler(reader_sp, cancel_top_handler); 10797ce2de2cSJonas Devlieghere } 10807ce2de2cSJonas Devlieghere 10817ca15ba7SLawrence D'Anna void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out, 1082b9c1b51eSKate Stone StreamFileSP &err) { 108305097246SAdrian Prantl // Before an IOHandler runs, it must have in/out/err streams. This function 108405097246SAdrian Prantl // is called when one ore more of the streams are nullptr. We use the top 108505097246SAdrian Prantl // input reader's in/out/err streams, or fall back to the debugger file 108605097246SAdrian Prantl // handles, or we fall back onto stdin/stdout/stderr as a last resort. 108744d93782SGreg Clayton 10887ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 10897ce2de2cSJonas Devlieghere IOHandlerSP top_reader_sp(m_io_handler_stack.Top()); 109044d93782SGreg Clayton // If no STDIN has been set, then set it appropriately 1091b07823f3SLawrence D'Anna if (!in || !in->IsValid()) { 109244d93782SGreg Clayton if (top_reader_sp) 10937ca15ba7SLawrence D'Anna in = top_reader_sp->GetInputFileSP(); 109444d93782SGreg Clayton else 10957ca15ba7SLawrence D'Anna in = GetInputFileSP(); 109644d93782SGreg Clayton // If there is nothing, use stdin 109744d93782SGreg Clayton if (!in) 1098f913fd6eSLawrence D'Anna in = std::make_shared<NativeFile>(stdin, false); 109944d93782SGreg Clayton } 110044d93782SGreg Clayton // If no STDOUT has been set, then set it appropriately 1101b07823f3SLawrence D'Anna if (!out || !out->GetFile().IsValid()) { 110244d93782SGreg Clayton if (top_reader_sp) 11037ca15ba7SLawrence D'Anna out = top_reader_sp->GetOutputStreamFileSP(); 110444d93782SGreg Clayton else 11057ca15ba7SLawrence D'Anna out = GetOutputStreamSP(); 110644d93782SGreg Clayton // If there is nothing, use stdout 110744d93782SGreg Clayton if (!out) 11082f3df613SZachary Turner out = std::make_shared<StreamFile>(stdout, false); 110944d93782SGreg Clayton } 111044d93782SGreg Clayton // If no STDERR has been set, then set it appropriately 1111b07823f3SLawrence D'Anna if (!err || !err->GetFile().IsValid()) { 111244d93782SGreg Clayton if (top_reader_sp) 11137ca15ba7SLawrence D'Anna err = top_reader_sp->GetErrorStreamFileSP(); 111444d93782SGreg Clayton else 11157ca15ba7SLawrence D'Anna err = GetErrorStreamSP(); 111644d93782SGreg Clayton // If there is nothing, use stderr 111744d93782SGreg Clayton if (!err) 11187ca15ba7SLawrence D'Anna err = std::make_shared<StreamFile>(stderr, false); 111944d93782SGreg Clayton } 112044d93782SGreg Clayton } 112144d93782SGreg Clayton 1122c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp, 1123c01783a8SRaphael Isemann bool cancel_top_handler) { 112430fdc8d8SChris Lattner if (!reader_sp) 112530fdc8d8SChris Lattner return; 1126b44880caSCaroline Tice 11277ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 11284446487dSPavel Labath 11294446487dSPavel Labath // Get the current top input reader... 11307ce2de2cSJonas Devlieghere IOHandlerSP top_reader_sp(m_io_handler_stack.Top()); 1131b44880caSCaroline Tice 1132b4874f1aSGreg Clayton // Don't push the same IO handler twice... 11334446487dSPavel Labath if (reader_sp == top_reader_sp) 11344446487dSPavel Labath return; 11354446487dSPavel Labath 113644d93782SGreg Clayton // Push our new input reader 11377ce2de2cSJonas Devlieghere m_io_handler_stack.Push(reader_sp); 11384446487dSPavel Labath reader_sp->Activate(); 113944d93782SGreg Clayton 114005097246SAdrian Prantl // Interrupt the top input reader to it will exit its Run() function and let 114105097246SAdrian Prantl // this new input reader take over 1142b9c1b51eSKate Stone if (top_reader_sp) { 114344d93782SGreg Clayton top_reader_sp->Deactivate(); 1144c01783a8SRaphael Isemann if (cancel_top_handler) 11454446487dSPavel Labath top_reader_sp->Cancel(); 114630fdc8d8SChris Lattner } 1147b4874f1aSGreg Clayton } 114830fdc8d8SChris Lattner 1149b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) { 11504446487dSPavel Labath if (!pop_reader_sp) 11514446487dSPavel Labath return false; 115230fdc8d8SChris Lattner 11537ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 115444d93782SGreg Clayton 115505097246SAdrian Prantl // The reader on the stop of the stack is done, so let the next read on the 115605097246SAdrian Prantl // stack refresh its prompt and if there is one... 11577ce2de2cSJonas Devlieghere if (m_io_handler_stack.IsEmpty()) 11584446487dSPavel Labath return false; 11594446487dSPavel Labath 11607ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 116130fdc8d8SChris Lattner 11624446487dSPavel Labath if (pop_reader_sp != reader_sp) 11634446487dSPavel Labath return false; 11644446487dSPavel Labath 116544d93782SGreg Clayton reader_sp->Deactivate(); 1166b4874f1aSGreg Clayton reader_sp->Cancel(); 11677ce2de2cSJonas Devlieghere m_io_handler_stack.Pop(); 116830fdc8d8SChris Lattner 11697ce2de2cSJonas Devlieghere reader_sp = m_io_handler_stack.Top(); 117030fdc8d8SChris Lattner if (reader_sp) 117144d93782SGreg Clayton reader_sp->Activate(); 117244d93782SGreg Clayton 117344d93782SGreg Clayton return true; 117430fdc8d8SChris Lattner } 11756611103cSGreg Clayton 1176b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() { 11772f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, true); 11785b52f0c7SJim Ingham } 11795b52f0c7SJim Ingham 1180b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() { 11812f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, false); 11825b52f0c7SJim Ingham } 11835b52f0c7SJim Ingham 1184b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() { 1185b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 11866c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 11876c42e063SGreg Clayton return g_debugger_list_ptr->size(); 1188061858ceSEnrico Granata } 1189c15f55e2SGreg Clayton return 0; 1190c15f55e2SGreg Clayton } 1191061858ceSEnrico Granata 1192b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) { 1193061858ceSEnrico Granata DebuggerSP debugger_sp; 1194061858ceSEnrico Granata 1195b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 11966c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 11976c42e063SGreg Clayton if (index < g_debugger_list_ptr->size()) 11986c42e063SGreg Clayton debugger_sp = g_debugger_list_ptr->at(index); 1199c15f55e2SGreg Clayton } 1200061858ceSEnrico Granata 1201061858ceSEnrico Granata return debugger_sp; 1202061858ceSEnrico Granata } 1203061858ceSEnrico Granata 1204b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) { 12054d122c40SGreg Clayton DebuggerSP debugger_sp; 1206ebc1bb27SCaroline Tice 1207b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 12086c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 12096c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 1210b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 1211b9c1b51eSKate Stone if ((*pos)->GetID() == id) { 1212ebc1bb27SCaroline Tice debugger_sp = *pos; 1213ebc1bb27SCaroline Tice break; 1214ebc1bb27SCaroline Tice } 1215ebc1bb27SCaroline Tice } 1216c15f55e2SGreg Clayton } 1217ebc1bb27SCaroline Tice return debugger_sp; 1218ebc1bb27SCaroline Tice } 12193df9a8dfSCaroline Tice 1220b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, 1221aff1b357SJason Molenda const SymbolContext *sc, 1222aff1b357SJason Molenda const SymbolContext *prev_sc, 1223aff1b357SJason Molenda const ExecutionContext *exe_ctx, 1224b9c1b51eSKate Stone const Address *addr, Stream &s) { 1225554f68d3SGreg Clayton FormatEntity::Entry format_entry; 1226554f68d3SGreg Clayton 1227b9c1b51eSKate Stone if (format == nullptr) { 1228df370550SEugene Zelenko if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) 1229aff1b357SJason Molenda format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1230b9c1b51eSKate Stone if (format == nullptr) { 1231554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format_entry); 1232554f68d3SGreg Clayton format = &format_entry; 1233554f68d3SGreg Clayton } 1234aff1b357SJason Molenda } 1235aff1b357SJason Molenda bool function_changed = false; 1236aff1b357SJason Molenda bool initial_function = false; 1237b9c1b51eSKate Stone if (prev_sc && (prev_sc->function || prev_sc->symbol)) { 1238b9c1b51eSKate Stone if (sc && (sc->function || sc->symbol)) { 1239b9c1b51eSKate Stone if (prev_sc->symbol && sc->symbol) { 1240b9c1b51eSKate Stone if (!sc->symbol->Compare(prev_sc->symbol->GetName(), 1241b9c1b51eSKate Stone prev_sc->symbol->GetType())) { 1242aff1b357SJason Molenda function_changed = true; 1243aff1b357SJason Molenda } 1244b9c1b51eSKate Stone } else if (prev_sc->function && sc->function) { 1245b9c1b51eSKate Stone if (prev_sc->function->GetMangled() != sc->function->GetMangled()) { 1246aff1b357SJason Molenda function_changed = true; 1247aff1b357SJason Molenda } 1248aff1b357SJason Molenda } 1249aff1b357SJason Molenda } 1250aff1b357SJason Molenda } 125105097246SAdrian Prantl // The first context on a list of instructions will have a prev_sc that has 125205097246SAdrian Prantl // no Function or Symbol -- if SymbolContext had an IsValid() method, it 1253aff1b357SJason Molenda // would return false. But we do get a prev_sc pointer. 1254b9c1b51eSKate Stone if ((sc && (sc->function || sc->symbol)) && prev_sc && 1255b9c1b51eSKate Stone (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) { 1256aff1b357SJason Molenda initial_function = true; 1257aff1b357SJason Molenda } 1258b9c1b51eSKate Stone return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, 1259b9c1b51eSKate Stone function_changed, initial_function); 1260aff1b357SJason Molenda } 1261aff1b357SJason Molenda 1262b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, 1263b9c1b51eSKate Stone void *baton) { 12644f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 12654f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 12664f02b22dSJim Ingham // callback. 12672f3df613SZachary Turner m_log_callback_stream_sp = 12682f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 1269228063cdSJim Ingham } 1270228063cdSJim Ingham 1271e122877fSGreg Clayton ConstString Debugger::ProgressEventData::GetFlavorString() { 1272e122877fSGreg Clayton static ConstString g_flavor("Debugger::ProgressEventData"); 1273e122877fSGreg Clayton return g_flavor; 1274e122877fSGreg Clayton } 1275e122877fSGreg Clayton 1276e122877fSGreg Clayton ConstString Debugger::ProgressEventData::GetFlavor() const { 1277e122877fSGreg Clayton return Debugger::ProgressEventData::GetFlavorString(); 1278e122877fSGreg Clayton } 1279e122877fSGreg Clayton 1280e122877fSGreg Clayton void Debugger::ProgressEventData::Dump(Stream *s) const { 1281e122877fSGreg Clayton s->Printf(" id = %" PRIu64 ", message = \"%s\"", m_id, m_message.c_str()); 1282e122877fSGreg Clayton if (m_completed == 0 || m_completed == m_total) 1283e122877fSGreg Clayton s->Printf(", type = %s", m_completed == 0 ? "start" : "end"); 1284e122877fSGreg Clayton else 1285e122877fSGreg Clayton s->PutCString(", type = update"); 1286e122877fSGreg Clayton // If m_total is UINT64_MAX, there is no progress to report, just "start" 1287e122877fSGreg Clayton // and "end". If it isn't we will show the completed and total amounts. 1288e122877fSGreg Clayton if (m_total != UINT64_MAX) 1289e122877fSGreg Clayton s->Printf(", progress = %" PRIu64 " of %" PRIu64, m_completed, m_total); 1290e122877fSGreg Clayton } 1291e122877fSGreg Clayton 1292e122877fSGreg Clayton const Debugger::ProgressEventData * 1293e122877fSGreg Clayton Debugger::ProgressEventData::GetEventDataFromEvent(const Event *event_ptr) { 1294e122877fSGreg Clayton if (event_ptr) 1295e122877fSGreg Clayton if (const EventData *event_data = event_ptr->GetData()) 1296e122877fSGreg Clayton if (event_data->GetFlavor() == ProgressEventData::GetFlavorString()) 1297e122877fSGreg Clayton return static_cast<const ProgressEventData *>(event_ptr->GetData()); 1298e122877fSGreg Clayton return nullptr; 1299e122877fSGreg Clayton } 1300e122877fSGreg Clayton 1301e122877fSGreg Clayton static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, 1302e122877fSGreg Clayton const std::string &message, 1303e122877fSGreg Clayton uint64_t completed, uint64_t total, 1304e122877fSGreg Clayton bool is_debugger_specific) { 1305e122877fSGreg Clayton // Only deliver progress events if we have any progress listeners. 1306e122877fSGreg Clayton const uint32_t event_type = Debugger::eBroadcastBitProgress; 1307e122877fSGreg Clayton if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type)) 1308e122877fSGreg Clayton return; 1309e122877fSGreg Clayton EventSP event_sp(new Event(event_type, new Debugger::ProgressEventData( 1310e122877fSGreg Clayton progress_id, message, completed, 1311e122877fSGreg Clayton total, is_debugger_specific))); 1312e122877fSGreg Clayton debugger.GetBroadcaster().BroadcastEvent(event_sp); 1313e122877fSGreg Clayton } 1314e122877fSGreg Clayton 1315e122877fSGreg Clayton void Debugger::ReportProgress(uint64_t progress_id, const std::string &message, 1316e122877fSGreg Clayton uint64_t completed, uint64_t total, 1317e122877fSGreg Clayton llvm::Optional<lldb::user_id_t> debugger_id) { 1318e122877fSGreg Clayton // Check if this progress is for a specific debugger. 1319e122877fSGreg Clayton if (debugger_id.hasValue()) { 1320e122877fSGreg Clayton // It is debugger specific, grab it and deliver the event if the debugger 1321e122877fSGreg Clayton // still exists. 1322e122877fSGreg Clayton DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id); 1323e122877fSGreg Clayton if (debugger_sp) 1324e122877fSGreg Clayton PrivateReportProgress(*debugger_sp, progress_id, message, completed, 1325e122877fSGreg Clayton total, /*is_debugger_specific*/ true); 1326e122877fSGreg Clayton return; 1327e122877fSGreg Clayton } 1328e122877fSGreg Clayton // The progress event is not debugger specific, iterate over all debuggers 1329e122877fSGreg Clayton // and deliver a progress event to each one. 1330e122877fSGreg Clayton if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 1331e122877fSGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 1332e122877fSGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 1333e122877fSGreg Clayton for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) 1334e122877fSGreg Clayton PrivateReportProgress(*(*pos), progress_id, message, completed, total, 1335e122877fSGreg Clayton /*is_debugger_specific*/ false); 1336e122877fSGreg Clayton } 1337e122877fSGreg Clayton } 1338e122877fSGreg Clayton 13395e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel, 13405e336903SPavel Labath llvm::ArrayRef<const char *> categories, 13415e336903SPavel Labath llvm::StringRef log_file, uint32_t log_options, 1342775588c0SPavel Labath llvm::raw_ostream &error_stream) { 13435fae71c5SPavel Labath const bool should_close = true; 13445fae71c5SPavel Labath const bool unbuffered = true; 13455fae71c5SPavel Labath 13465fae71c5SPavel Labath std::shared_ptr<llvm::raw_ostream> log_stream_sp; 1347b9c1b51eSKate Stone if (m_log_callback_stream_sp) { 1348228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 1349228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 1350b9c1b51eSKate Stone log_options |= 1351b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 13525e336903SPavel Labath } else if (log_file.empty()) { 13535fae71c5SPavel Labath log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( 13547ca15ba7SLawrence D'Anna GetOutputFile().GetDescriptor(), !should_close, unbuffered); 1355b9c1b51eSKate Stone } else { 13565fae71c5SPavel Labath auto pos = m_log_streams.find(log_file); 1357c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 1358c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 1359b9c1b51eSKate Stone if (!log_stream_sp) { 13606b2e6765SJonas Devlieghere File::OpenOptions flags = 136114735cabSMichał Górny File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate; 13625fae71c5SPavel Labath if (log_options & LLDB_LOG_OPTION_APPEND) 13636b2e6765SJonas Devlieghere flags |= File::eOpenOptionAppend; 13646b2e6765SJonas Devlieghere else 13656b2e6765SJonas Devlieghere flags |= File::eOpenOptionTruncate; 1366867c347cSRaphael Isemann llvm::Expected<FileUP> file = FileSystem::Instance().Open( 13676b2e6765SJonas Devlieghere FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false); 13686b2e6765SJonas Devlieghere if (!file) { 1369867c347cSRaphael Isemann error_stream << "Unable to open log file '" << log_file 1370867c347cSRaphael Isemann << "': " << llvm::toString(file.takeError()) << "\n"; 13715fae71c5SPavel Labath return false; 13725fae71c5SPavel Labath } 13736b2e6765SJonas Devlieghere 13746b2e6765SJonas Devlieghere log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( 13756b2e6765SJonas Devlieghere (*file)->GetDescriptor(), should_close, unbuffered); 1376228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 1377228063cdSJim Ingham } 1378228063cdSJim Ingham } 1379df370550SEugene Zelenko assert(log_stream_sp); 1380228063cdSJim Ingham 1381228063cdSJim Ingham if (log_options == 0) 1382b9c1b51eSKate Stone log_options = 1383b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 1384228063cdSJim Ingham 1385b9c1b51eSKate Stone return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories, 1386b9c1b51eSKate Stone error_stream); 1387228063cdSJim Ingham } 1388228063cdSJim Ingham 1389bbf70c04SJonas Devlieghere ScriptInterpreter * 1390bbf70c04SJonas Devlieghere Debugger::GetScriptInterpreter(bool can_create, 1391bbf70c04SJonas Devlieghere llvm::Optional<lldb::ScriptLanguage> language) { 13922b29b432SJonas Devlieghere std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex); 1393bbf70c04SJonas Devlieghere lldb::ScriptLanguage script_language = 1394bbf70c04SJonas Devlieghere language ? *language : GetScriptLanguage(); 13952b29b432SJonas Devlieghere 1396bbf70c04SJonas Devlieghere if (!m_script_interpreters[script_language]) { 13972b29b432SJonas Devlieghere if (!can_create) 13982b29b432SJonas Devlieghere return nullptr; 1399bbf70c04SJonas Devlieghere m_script_interpreters[script_language] = 1400bbf70c04SJonas Devlieghere PluginManager::GetScriptInterpreterForLanguage(script_language, *this); 14012b29b432SJonas Devlieghere } 14022b29b432SJonas Devlieghere 1403bbf70c04SJonas Devlieghere return m_script_interpreters[script_language].get(); 14042b29b432SJonas Devlieghere } 14052b29b432SJonas Devlieghere 1406b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() { 1407d5b44036SJonas Devlieghere if (!m_source_manager_up) 1408a8f3ae7cSJonas Devlieghere m_source_manager_up = std::make_unique<SourceManager>(shared_from_this()); 1409d5b44036SJonas Devlieghere return *m_source_manager_up; 14109585fbfcSGreg Clayton } 14119585fbfcSGreg Clayton 141244d93782SGreg Clayton // This function handles events that were broadcast by the process. 1413b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) { 141444d93782SGreg Clayton using namespace lldb; 1415b9c1b51eSKate Stone const uint32_t event_type = 1416b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 1417b9c1b51eSKate Stone event_sp); 141844d93782SGreg Clayton 141944d93782SGreg Clayton // if (event_type & eBreakpointEventTypeAdded 142044d93782SGreg Clayton // || event_type & eBreakpointEventTypeRemoved 142144d93782SGreg Clayton // || event_type & eBreakpointEventTypeEnabled 142244d93782SGreg Clayton // || event_type & eBreakpointEventTypeDisabled 142344d93782SGreg Clayton // || event_type & eBreakpointEventTypeCommandChanged 142444d93782SGreg Clayton // || event_type & eBreakpointEventTypeConditionChanged 142544d93782SGreg Clayton // || event_type & eBreakpointEventTypeIgnoreChanged 142644d93782SGreg Clayton // || event_type & eBreakpointEventTypeLocationsResolved) 142744d93782SGreg Clayton // { 1428b9c1b51eSKate Stone // // Don't do anything about these events, since the breakpoint 1429b9c1b51eSKate Stone // commands already echo these actions. 143044d93782SGreg Clayton // } 143144d93782SGreg Clayton // 1432b9c1b51eSKate Stone if (event_type & eBreakpointEventTypeLocationsAdded) { 1433b9c1b51eSKate Stone uint32_t num_new_locations = 1434b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 1435b9c1b51eSKate Stone event_sp); 1436b9c1b51eSKate Stone if (num_new_locations > 0) { 1437b9c1b51eSKate Stone BreakpointSP breakpoint = 1438b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 14394446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1440b9c1b51eSKate Stone if (output_sp) { 144144d93782SGreg Clayton output_sp->Printf("%d location%s added to breakpoint %d\n", 1442b9c1b51eSKate Stone num_new_locations, num_new_locations == 1 ? "" : "s", 144344d93782SGreg Clayton breakpoint->GetID()); 14444446487dSPavel Labath output_sp->Flush(); 144544d93782SGreg Clayton } 144644d93782SGreg Clayton } 144744d93782SGreg Clayton } 144844d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsRemoved) 144944d93782SGreg Clayton // { 1450b9c1b51eSKate Stone // // These locations just get disabled, not sure it is worth spamming 1451b9c1b51eSKate Stone // folks about this on the command line. 145244d93782SGreg Clayton // } 145344d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsResolved) 145444d93782SGreg Clayton // { 1455b9c1b51eSKate Stone // // This might be an interesting thing to note, but I'm going to 1456b9c1b51eSKate Stone // leave it quiet for now, it just looked noisy. 145744d93782SGreg Clayton // } 145844d93782SGreg Clayton } 145944d93782SGreg Clayton 1460a9d58436SPavel Labath void Debugger::FlushProcessOutput(Process &process, bool flush_stdout, 1461a9d58436SPavel Labath bool flush_stderr) { 1462a9d58436SPavel Labath const auto &flush = [&](Stream &stream, 1463a9d58436SPavel Labath size_t (Process::*get)(char *, size_t, Status &)) { 146497206d57SZachary Turner Status error; 146544d93782SGreg Clayton size_t len; 1466a9d58436SPavel Labath char buffer[1024]; 1467a9d58436SPavel Labath while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0) 1468a9d58436SPavel Labath stream.Write(buffer, len); 1469a9d58436SPavel Labath stream.Flush(); 1470a9d58436SPavel Labath }; 147144d93782SGreg Clayton 1472a9d58436SPavel Labath std::lock_guard<std::mutex> guard(m_output_flush_mutex); 1473a9d58436SPavel Labath if (flush_stdout) 1474a9d58436SPavel Labath flush(*GetAsyncOutputStream(), &Process::GetSTDOUT); 1475a9d58436SPavel Labath if (flush_stderr) 1476a9d58436SPavel Labath flush(*GetAsyncErrorStream(), &Process::GetSTDERR); 147744d93782SGreg Clayton } 147844d93782SGreg Clayton 147944d93782SGreg Clayton // This function handles events that were broadcast by the process. 1480b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) { 148144d93782SGreg Clayton using namespace lldb; 148244d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 1483b9c1b51eSKate Stone ProcessSP process_sp = 1484b9c1b51eSKate Stone (event_type == Process::eBroadcastBitStructuredData) 148575930019STodd Fiala ? EventDataStructuredData::GetProcessFromEvent(event_sp.get()) 148675930019STodd Fiala : Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 148744d93782SGreg Clayton 14884446487dSPavel Labath StreamSP output_stream_sp = GetAsyncOutputStream(); 14894446487dSPavel Labath StreamSP error_stream_sp = GetAsyncErrorStream(); 149044d93782SGreg Clayton const bool gui_enabled = IsForwardingEvents(); 149144d93782SGreg Clayton 1492b9c1b51eSKate Stone if (!gui_enabled) { 1493b4874f1aSGreg Clayton bool pop_process_io_handler = false; 149444d93782SGreg Clayton assert(process_sp); 149544d93782SGreg Clayton 14964446487dSPavel Labath bool state_is_stopped = false; 1497b9c1b51eSKate Stone const bool got_state_changed = 1498b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStateChanged) != 0; 14994446487dSPavel Labath const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0; 15004446487dSPavel Labath const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0; 1501b9c1b51eSKate Stone const bool got_structured_data = 1502b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStructuredData) != 0; 150375930019STodd Fiala 1504b9c1b51eSKate Stone if (got_state_changed) { 1505b9c1b51eSKate Stone StateType event_state = 1506b9c1b51eSKate Stone Process::ProcessEventData::GetStateFromEvent(event_sp.get()); 15074446487dSPavel Labath state_is_stopped = StateIsStoppedState(event_state, false); 150844d93782SGreg Clayton } 1509b4874f1aSGreg Clayton 15104446487dSPavel Labath // Display running state changes first before any STDIO 1511b9c1b51eSKate Stone if (got_state_changed && !state_is_stopped) { 1512b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1513b9c1b51eSKate Stone pop_process_io_handler); 151444d93782SGreg Clayton } 1515b4874f1aSGreg Clayton 1516a9d58436SPavel Labath // Now display STDOUT and STDERR 1517a9d58436SPavel Labath FlushProcessOutput(*process_sp, got_stdout || got_state_changed, 1518a9d58436SPavel Labath got_stderr || got_state_changed); 1519b4874f1aSGreg Clayton 152075930019STodd Fiala // Give structured data events an opportunity to display. 1521b9c1b51eSKate Stone if (got_structured_data) { 152275930019STodd Fiala StructuredDataPluginSP plugin_sp = 152375930019STodd Fiala EventDataStructuredData::GetPluginFromEvent(event_sp.get()); 1524b9c1b51eSKate Stone if (plugin_sp) { 152575930019STodd Fiala auto structured_data_sp = 152675930019STodd Fiala EventDataStructuredData::GetObjectFromEvent(event_sp.get()); 1527b9c1b51eSKate Stone if (output_stream_sp) { 152875930019STodd Fiala StreamString content_stream; 152997206d57SZachary Turner Status error = 1530b9c1b51eSKate Stone plugin_sp->GetDescription(structured_data_sp, content_stream); 1531b9c1b51eSKate Stone if (error.Success()) { 1532b9c1b51eSKate Stone if (!content_stream.GetString().empty()) { 153375930019STodd Fiala // Add newline. 153475930019STodd Fiala content_stream.PutChar('\n'); 153575930019STodd Fiala content_stream.Flush(); 153675930019STodd Fiala 153775930019STodd Fiala // Print it. 1538771ef6d4SMalcolm Parsons output_stream_sp->PutCString(content_stream.GetString()); 153975930019STodd Fiala } 1540b9c1b51eSKate Stone } else { 1541a3939e15SPavel Labath error_stream_sp->Format("Failed to print structured " 1542a3939e15SPavel Labath "data with plugin {0}: {1}", 1543a3939e15SPavel Labath plugin_sp->GetPluginName(), error); 154475930019STodd Fiala } 154575930019STodd Fiala } 154675930019STodd Fiala } 154775930019STodd Fiala } 154875930019STodd Fiala 15494446487dSPavel Labath // Now display any stopped state changes after any STDIO 1550b9c1b51eSKate Stone if (got_state_changed && state_is_stopped) { 1551b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1552b9c1b51eSKate Stone pop_process_io_handler); 155344d93782SGreg Clayton } 155444d93782SGreg Clayton 15554446487dSPavel Labath output_stream_sp->Flush(); 15564446487dSPavel Labath error_stream_sp->Flush(); 155744d93782SGreg Clayton 1558b4874f1aSGreg Clayton if (pop_process_io_handler) 1559b4874f1aSGreg Clayton process_sp->PopProcessIOHandler(); 1560b4874f1aSGreg Clayton } 1561b4874f1aSGreg Clayton } 1562b4874f1aSGreg Clayton 1563b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) { 156405097246SAdrian Prantl // At present the only thread event we handle is the Frame Changed event, and 156505097246SAdrian Prantl // all we do for that is just reprint the thread status for that thread. 156644d93782SGreg Clayton using namespace lldb; 156744d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 15686a9767c7SJim Ingham const bool stop_format = true; 156944d93782SGreg Clayton if (event_type == Thread::eBroadcastBitStackChanged || 1570b9c1b51eSKate Stone event_type == Thread::eBroadcastBitThreadSelected) { 1571b9c1b51eSKate Stone ThreadSP thread_sp( 1572b9c1b51eSKate Stone Thread::ThreadEventData::GetThreadFromEvent(event_sp.get())); 1573b9c1b51eSKate Stone if (thread_sp) { 15746a9767c7SJim Ingham thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format); 157544d93782SGreg Clayton } 157644d93782SGreg Clayton } 157744d93782SGreg Clayton } 157844d93782SGreg Clayton 1579b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; } 158044d93782SGreg Clayton 1581b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) { 158244d93782SGreg Clayton m_forward_listener_sp = listener_sp; 158344d93782SGreg Clayton } 158444d93782SGreg Clayton 1585b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) { 158644d93782SGreg Clayton m_forward_listener_sp.reset(); 158744d93782SGreg Clayton } 158844d93782SGreg Clayton 1589d0810779SPavel Labath lldb::thread_result_t Debugger::DefaultEventHandler() { 1590583bbb1dSJim Ingham ListenerSP listener_sp(GetListener()); 159144d93782SGreg Clayton ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 159244d93782SGreg Clayton ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 159344d93782SGreg Clayton ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 159444d93782SGreg Clayton BroadcastEventSpec target_event_spec(broadcaster_class_target, 159544d93782SGreg Clayton Target::eBroadcastBitBreakpointChanged); 159644d93782SGreg Clayton 1597b9c1b51eSKate Stone BroadcastEventSpec process_event_spec( 1598b9c1b51eSKate Stone broadcaster_class_process, 1599b9c1b51eSKate Stone Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT | 1600b9c1b51eSKate Stone Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData); 160144d93782SGreg Clayton 160244d93782SGreg Clayton BroadcastEventSpec thread_event_spec(broadcaster_class_thread, 160344d93782SGreg Clayton Thread::eBroadcastBitStackChanged | 160444d93782SGreg Clayton Thread::eBroadcastBitThreadSelected); 160544d93782SGreg Clayton 1606b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1607b9c1b51eSKate Stone target_event_spec); 1608b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1609b9c1b51eSKate Stone process_event_spec); 1610b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1611b9c1b51eSKate Stone thread_event_spec); 1612b9c1b51eSKate Stone listener_sp->StartListeningForEvents( 1613d5b44036SJonas Devlieghere m_command_interpreter_up.get(), 161444d93782SGreg Clayton CommandInterpreter::eBroadcastBitQuitCommandReceived | 161544d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousOutputData | 161644d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousErrorData); 161744d93782SGreg Clayton 161805097246SAdrian Prantl // Let the thread that spawned us know that we have started up and that we 161905097246SAdrian Prantl // are now listening to all required events so no events get missed 1620afa91e33SGreg Clayton m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); 1621afa91e33SGreg Clayton 162244d93782SGreg Clayton bool done = false; 1623b9c1b51eSKate Stone while (!done) { 162444d93782SGreg Clayton EventSP event_sp; 1625d35031e1SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 1626b9c1b51eSKate Stone if (event_sp) { 162744d93782SGreg Clayton Broadcaster *broadcaster = event_sp->GetBroadcaster(); 1628b9c1b51eSKate Stone if (broadcaster) { 162944d93782SGreg Clayton uint32_t event_type = event_sp->GetType(); 163044d93782SGreg Clayton ConstString broadcaster_class(broadcaster->GetBroadcasterClass()); 1631b9c1b51eSKate Stone if (broadcaster_class == broadcaster_class_process) { 163244d93782SGreg Clayton HandleProcessEvent(event_sp); 1633b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_target) { 1634b9c1b51eSKate Stone if (Breakpoint::BreakpointEventData::GetEventDataFromEvent( 1635b9c1b51eSKate Stone event_sp.get())) { 163644d93782SGreg Clayton HandleBreakpointEvent(event_sp); 163744d93782SGreg Clayton } 1638b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_thread) { 163944d93782SGreg Clayton HandleThreadEvent(event_sp); 1640d5b44036SJonas Devlieghere } else if (broadcaster == m_command_interpreter_up.get()) { 1641b9c1b51eSKate Stone if (event_type & 1642b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived) { 164344d93782SGreg Clayton done = true; 1644b9c1b51eSKate Stone } else if (event_type & 1645b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitAsynchronousErrorData) { 164665fdb342SRaphael Isemann const char *data = static_cast<const char *>( 1647b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1648b9c1b51eSKate Stone if (data && data[0]) { 16494446487dSPavel Labath StreamSP error_sp(GetAsyncErrorStream()); 1650b9c1b51eSKate Stone if (error_sp) { 165144d93782SGreg Clayton error_sp->PutCString(data); 165244d93782SGreg Clayton error_sp->Flush(); 165344d93782SGreg Clayton } 165444d93782SGreg Clayton } 1655b9c1b51eSKate Stone } else if (event_type & CommandInterpreter:: 1656b9c1b51eSKate Stone eBroadcastBitAsynchronousOutputData) { 165765fdb342SRaphael Isemann const char *data = static_cast<const char *>( 1658b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1659b9c1b51eSKate Stone if (data && data[0]) { 16604446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1661b9c1b51eSKate Stone if (output_sp) { 166244d93782SGreg Clayton output_sp->PutCString(data); 166344d93782SGreg Clayton output_sp->Flush(); 166444d93782SGreg Clayton } 166544d93782SGreg Clayton } 166644d93782SGreg Clayton } 166744d93782SGreg Clayton } 166844d93782SGreg Clayton } 166944d93782SGreg Clayton 167044d93782SGreg Clayton if (m_forward_listener_sp) 167144d93782SGreg Clayton m_forward_listener_sp->AddEvent(event_sp); 167244d93782SGreg Clayton } 167344d93782SGreg Clayton } 167444d93782SGreg Clayton } 167585200645SKonrad Kleine return {}; 167644d93782SGreg Clayton } 167744d93782SGreg Clayton 1678b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() { 1679b9c1b51eSKate Stone if (!m_event_handler_thread.IsJoinable()) { 168005097246SAdrian Prantl // We must synchronize with the DefaultEventHandler() thread to ensure it 168105097246SAdrian Prantl // is up and running and listening to events before we return from this 168205097246SAdrian Prantl // function. We do this by listening to events for the 1683afa91e33SGreg Clayton // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster 16841a728f66STatyana Krasnukha ConstString full_name("lldb.debugger.event-handler"); 16851a728f66STatyana Krasnukha ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString())); 1686b9c1b51eSKate Stone listener_sp->StartListeningForEvents(&m_sync_broadcaster, 1687b9c1b51eSKate Stone eBroadcastBitEventThreadIsListening); 1688afa91e33SGreg Clayton 1689642bc15dSRaphael Isemann llvm::StringRef thread_name = 1690e063ecccSJonas Devlieghere full_name.GetLength() < llvm::get_max_thread_name_length() 1691642bc15dSRaphael Isemann ? full_name.GetStringRef() 1692e063ecccSJonas Devlieghere : "dbg.evt-handler"; 16931a728f66STatyana Krasnukha 16947c2896a2SZachary Turner // Use larger 8MB stack for this thread 1695f39c2e18SJonas Devlieghere llvm::Expected<HostThread> event_handler_thread = 1696d0810779SPavel Labath ThreadLauncher::LaunchThread( 1697d0810779SPavel Labath thread_name, [this] { return DefaultEventHandler(); }, 1698f39c2e18SJonas Devlieghere g_debugger_event_thread_stack_bytes); 1699f39c2e18SJonas Devlieghere 1700f39c2e18SJonas Devlieghere if (event_handler_thread) { 1701f39c2e18SJonas Devlieghere m_event_handler_thread = *event_handler_thread; 1702f39c2e18SJonas Devlieghere } else { 1703a007a6d8SPavel Labath LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", 1704f39c2e18SJonas Devlieghere llvm::toString(event_handler_thread.takeError())); 1705f39c2e18SJonas Devlieghere } 1706afa91e33SGreg Clayton 170705097246SAdrian Prantl // Make sure DefaultEventHandler() is running and listening to events 170805097246SAdrian Prantl // before we return from this function. We are only listening for events of 170905097246SAdrian Prantl // type eBroadcastBitEventThreadIsListening so we don't need to check the 171005097246SAdrian Prantl // event, we just need to wait an infinite amount of time for it (nullptr 171105097246SAdrian Prantl // timeout as the first parameter) 1712afa91e33SGreg Clayton lldb::EventSP event_sp; 1713d35031e1SPavel Labath listener_sp->GetEvent(event_sp, llvm::None); 1714807b6b32SGreg Clayton } 1715acee96aeSZachary Turner return m_event_handler_thread.IsJoinable(); 171644d93782SGreg Clayton } 171744d93782SGreg Clayton 1718b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() { 1719b9c1b51eSKate Stone if (m_event_handler_thread.IsJoinable()) { 1720b9c1b51eSKate Stone GetCommandInterpreter().BroadcastEvent( 1721b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived); 172239de3110SZachary Turner m_event_handler_thread.Join(nullptr); 172344d93782SGreg Clayton } 172444d93782SGreg Clayton } 172544d93782SGreg Clayton 1726d0810779SPavel Labath lldb::thread_result_t Debugger::IOHandlerThread() { 1727d0810779SPavel Labath RunIOHandlers(); 1728d0810779SPavel Labath StopEventHandlerThread(); 172985200645SKonrad Kleine return {}; 173044d93782SGreg Clayton } 173144d93782SGreg Clayton 1732b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } 17336681041dSSean Callanan 1734b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() { 1735f39c2e18SJonas Devlieghere if (!m_io_handler_thread.IsJoinable()) { 1736f39c2e18SJonas Devlieghere llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread( 1737d0810779SPavel Labath "lldb.debugger.io-handler", [this] { return IOHandlerThread(); }, 1738807b6b32SGreg Clayton 8 * 1024 * 1024); // Use larger 8MB stack for this thread 1739f39c2e18SJonas Devlieghere if (io_handler_thread) { 1740f39c2e18SJonas Devlieghere m_io_handler_thread = *io_handler_thread; 1741f39c2e18SJonas Devlieghere } else { 1742a007a6d8SPavel Labath LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", 1743f39c2e18SJonas Devlieghere llvm::toString(io_handler_thread.takeError())); 1744f39c2e18SJonas Devlieghere } 1745f39c2e18SJonas Devlieghere } 1746acee96aeSZachary Turner return m_io_handler_thread.IsJoinable(); 174744d93782SGreg Clayton } 174844d93782SGreg Clayton 1749b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() { 1750b9c1b51eSKate Stone if (m_io_handler_thread.IsJoinable()) { 17517ca15ba7SLawrence D'Anna GetInputFile().Close(); 175239de3110SZachary Turner m_io_handler_thread.Join(nullptr); 175344d93782SGreg Clayton } 175444d93782SGreg Clayton } 175544d93782SGreg Clayton 1756b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() { 1757b9c1b51eSKate Stone if (HasIOHandlerThread()) { 17586681041dSSean Callanan thread_result_t result; 17596681041dSSean Callanan m_io_handler_thread.Join(&result); 17606681041dSSean Callanan m_io_handler_thread = LLDB_INVALID_HOST_THREAD; 17616681041dSSean Callanan } 17626681041dSSean Callanan } 17636681041dSSean Callanan 1764b2fa3b92SJonas Devlieghere Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { 1765b9c1b51eSKate Stone if (!prefer_dummy) { 1766b2fa3b92SJonas Devlieghere if (TargetSP target = m_target_list.GetSelectedTarget()) 1767b2fa3b92SJonas Devlieghere return *target; 176833df7cd3SJim Ingham } 1769893c932aSJim Ingham return GetDummyTarget(); 1770893c932aSJim Ingham } 177144d93782SGreg Clayton 177297206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) { 177397206d57SZachary Turner Status err; 17743e7e915dSSean Callanan FileSpec repl_executable; 17753e7e915dSSean Callanan 177646a28a95SJonas Devlieghere if (language == eLanguageTypeUnknown) 177746a28a95SJonas Devlieghere language = GetREPLLanguage(); 177846a28a95SJonas Devlieghere 1779b9c1b51eSKate Stone if (language == eLanguageTypeUnknown) { 1780aa97a89dSAdrian Prantl LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs(); 178197f84e87SSean Callanan 1782aa97a89dSAdrian Prantl if (auto single_lang = repl_languages.GetSingularLanguage()) { 1783aa97a89dSAdrian Prantl language = *single_lang; 1784aa97a89dSAdrian Prantl } else if (repl_languages.Empty()) { 178546a28a95SJonas Devlieghere err.SetErrorString( 1786b9c1b51eSKate Stone "LLDB isn't configured with REPL support for any languages."); 178797f84e87SSean Callanan return err; 1788b9c1b51eSKate Stone } else { 178946a28a95SJonas Devlieghere err.SetErrorString( 1790b9c1b51eSKate Stone "Multiple possible REPL languages. Please specify a language."); 179197f84e87SSean Callanan return err; 179297f84e87SSean Callanan } 179397f84e87SSean Callanan } 179497f84e87SSean Callanan 1795b9c1b51eSKate Stone Target *const target = 1796b9c1b51eSKate Stone nullptr; // passing in an empty target means the REPL must create one 17973e7e915dSSean Callanan 17983b682de6SSean Callanan REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); 17993e7e915dSSean Callanan 1800b9c1b51eSKate Stone if (!err.Success()) { 18013e7e915dSSean Callanan return err; 18023e7e915dSSean Callanan } 18033e7e915dSSean Callanan 1804b9c1b51eSKate Stone if (!repl_sp) { 1805b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't find a REPL for %s", 1806b9c1b51eSKate Stone Language::GetNameForLanguageType(language)); 18073e7e915dSSean Callanan return err; 18083e7e915dSSean Callanan } 18093e7e915dSSean Callanan 18103e7e915dSSean Callanan repl_sp->SetCompilerOptions(repl_options); 18113e7e915dSSean Callanan repl_sp->RunLoop(); 18123e7e915dSSean Callanan 18133e7e915dSSean Callanan return err; 18143e7e915dSSean Callanan } 1815