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" 125e65e79bSJonas Devlieghere #include "lldb/Core/DebuggerEvents.h" 13554f68d3SGreg Clayton #include "lldb/Core/FormatEntity.h" 14672d2c12SJonas Devlieghere #include "lldb/Core/Mangled.h" 15672d2c12SJonas Devlieghere #include "lldb/Core/ModuleList.h" 16e8cd0c98SGreg Clayton #include "lldb/Core/PluginManager.h" 175b52f0c7SJim Ingham #include "lldb/Core/StreamAsynchronousIO.h" 1844d93782SGreg Clayton #include "lldb/Core/StreamFile.h" 195548cb50SEnrico Granata #include "lldb/DataFormatters/DataVisualization.h" 203e7e915dSSean Callanan #include "lldb/Expression/REPL.h" 21672d2c12SJonas Devlieghere #include "lldb/Host/File.h" 2235e4c84cSJonas Devlieghere #include "lldb/Host/FileSystem.h" 2342ff0ad8SZachary Turner #include "lldb/Host/HostInfo.h" 24a3406614SGreg Clayton #include "lldb/Host/Terminal.h" 2539de3110SZachary Turner #include "lldb/Host/ThreadLauncher.h" 266611103cSGreg Clayton #include "lldb/Interpreter/CommandInterpreter.h" 27d6b64612SMed Ismail Bennani #include "lldb/Interpreter/CommandReturnObject.h" 28672d2c12SJonas Devlieghere #include "lldb/Interpreter/OptionValue.h" 2946a28a95SJonas Devlieghere #include "lldb/Interpreter/OptionValueLanguage.h" 30633a29cfSZachary Turner #include "lldb/Interpreter/OptionValueProperties.h" 3167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueSInt64.h" 3267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueString.h" 33672d2c12SJonas Devlieghere #include "lldb/Interpreter/Property.h" 34672d2c12SJonas Devlieghere #include "lldb/Interpreter/ScriptInterpreter.h" 351f746071SGreg Clayton #include "lldb/Symbol/Function.h" 361f746071SGreg Clayton #include "lldb/Symbol/Symbol.h" 37672d2c12SJonas Devlieghere #include "lldb/Symbol/SymbolContext.h" 383e7e915dSSean Callanan #include "lldb/Target/Language.h" 3930fdc8d8SChris Lattner #include "lldb/Target/Process.h" 4075930019STodd Fiala #include "lldb/Target/StructuredDataPlugin.h" 4184a53dfbSEnrico Granata #include "lldb/Target/Target.h" 42b9c1b51eSKate Stone #include "lldb/Target/TargetList.h" 4330fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 44672d2c12SJonas Devlieghere #include "lldb/Target/ThreadList.h" 455a31471eSGreg Clayton #include "lldb/Utility/AnsiTerminal.h" 46181b823bSPavel Labath #include "lldb/Utility/Event.h" 47c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h" 48181b823bSPavel Labath #include "lldb/Utility/Listener.h" 49672d2c12SJonas Devlieghere #include "lldb/Utility/Log.h" 509e046f02SJonas Devlieghere #include "lldb/Utility/Reproducer.h" 51f23b829aSLevon Ter-Grigoryan #include "lldb/Utility/ReproducerProvider.h" 52d821c997SPavel Labath #include "lldb/Utility/State.h" 53672d2c12SJonas Devlieghere #include "lldb/Utility/Stream.h" 54fb1a0a0dSZachary Turner #include "lldb/Utility/StreamCallback.h" 55bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 562f3df613SZachary Turner 57b1cb0b79SNico Weber #if defined(_WIN32) 58672d2c12SJonas Devlieghere #include "lldb/Host/windows/PosixApi.h" 598aa23614SDavid Bolvansky #include "lldb/Host/windows/windows.h" 602f3df613SZachary Turner #endif 612f3df613SZachary Turner 62672d2c12SJonas Devlieghere #include "llvm/ADT/None.h" 63672d2c12SJonas Devlieghere #include "llvm/ADT/STLExtras.h" 642f3df613SZachary Turner #include "llvm/ADT/StringRef.h" 65672d2c12SJonas Devlieghere #include "llvm/ADT/iterator.h" 662f3df613SZachary Turner #include "llvm/Support/DynamicLibrary.h" 672f3df613SZachary Turner #include "llvm/Support/FileSystem.h" 688aa23614SDavid Bolvansky #include "llvm/Support/Process.h" 692f3df613SZachary Turner #include "llvm/Support/Threading.h" 70672d2c12SJonas Devlieghere #include "llvm/Support/raw_ostream.h" 712f3df613SZachary Turner 7276e47d48SRaphael Isemann #include <cstdio> 7376e47d48SRaphael Isemann #include <cstdlib> 7476e47d48SRaphael Isemann #include <cstring> 75672d2c12SJonas Devlieghere #include <list> 76672d2c12SJonas Devlieghere #include <memory> 772f3df613SZachary Turner #include <mutex> 78672d2c12SJonas Devlieghere #include <set> 79672d2c12SJonas Devlieghere #include <string> 80672d2c12SJonas Devlieghere #include <system_error> 812f3df613SZachary Turner 82f23b829aSLevon Ter-Grigoryan // Includes for pipe() 83f23b829aSLevon Ter-Grigoryan #if defined(_WIN32) 84f23b829aSLevon Ter-Grigoryan #include <fcntl.h> 85f23b829aSLevon Ter-Grigoryan #include <io.h> 86f23b829aSLevon Ter-Grigoryan #else 87f23b829aSLevon Ter-Grigoryan #include <unistd.h> 88f23b829aSLevon Ter-Grigoryan #endif 89f23b829aSLevon Ter-Grigoryan 902f3df613SZachary Turner namespace lldb_private { 912f3df613SZachary Turner class Address; 922f3df613SZachary Turner } 9330fdc8d8SChris Lattner 9430fdc8d8SChris Lattner using namespace lldb; 9530fdc8d8SChris Lattner using namespace lldb_private; 9630fdc8d8SChris Lattner 97ebc1bb27SCaroline Tice static lldb::user_id_t g_unique_id = 1; 987c2896a2SZachary Turner static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; 99ebc1bb27SCaroline Tice 1001b654882SGreg Clayton #pragma mark Static Functions 1011b654882SGreg Clayton 1021b654882SGreg Clayton typedef std::vector<DebuggerSP> DebuggerList; 103b9c1b51eSKate Stone static std::recursive_mutex *g_debugger_list_mutex_ptr = 104b9c1b51eSKate Stone nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain 105b9c1b51eSKate Stone static DebuggerList *g_debugger_list_ptr = 106b9c1b51eSKate Stone nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain 107e372b98dSGreg Clayton 1088fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = { 109e063ecccSJonas Devlieghere { 110e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNever, 111e063ecccSJonas Devlieghere "never", 112e063ecccSJonas Devlieghere "Never show disassembly when displaying a stop context.", 113e063ecccSJonas Devlieghere }, 114e063ecccSJonas Devlieghere { 115e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoDebugInfo, 116e063ecccSJonas Devlieghere "no-debuginfo", 117e063ecccSJonas Devlieghere "Show disassembly when there is no debug information.", 118e063ecccSJonas Devlieghere }, 119e063ecccSJonas Devlieghere { 120e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeNoSource, 121e063ecccSJonas Devlieghere "no-source", 122e063ecccSJonas Devlieghere "Show disassembly when there is no source information, or the source " 123e063ecccSJonas Devlieghere "file " 124e063ecccSJonas Devlieghere "is missing when displaying a stop context.", 125e063ecccSJonas Devlieghere }, 126e063ecccSJonas Devlieghere { 127e063ecccSJonas Devlieghere Debugger::eStopDisassemblyTypeAlways, 128e063ecccSJonas Devlieghere "always", 129e063ecccSJonas Devlieghere "Always show disassembly when displaying a stop context.", 130e063ecccSJonas Devlieghere }, 131e063ecccSJonas Devlieghere }; 132e372b98dSGreg Clayton 1338fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_language_enumerators[] = { 134e063ecccSJonas Devlieghere { 135e063ecccSJonas Devlieghere eScriptLanguageNone, 136e063ecccSJonas Devlieghere "none", 137e063ecccSJonas Devlieghere "Disable scripting languages.", 138e063ecccSJonas Devlieghere }, 139e063ecccSJonas Devlieghere { 140e063ecccSJonas Devlieghere eScriptLanguagePython, 141e063ecccSJonas Devlieghere "python", 142e063ecccSJonas Devlieghere "Select python as the default scripting language.", 143e063ecccSJonas Devlieghere }, 144e063ecccSJonas Devlieghere { 145e063ecccSJonas Devlieghere eScriptLanguageDefault, 146e063ecccSJonas Devlieghere "default", 147e063ecccSJonas Devlieghere "Select the lldb default as the default scripting language.", 148e063ecccSJonas Devlieghere }, 149e063ecccSJonas Devlieghere }; 150e372b98dSGreg Clayton 1518fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement s_stop_show_column_values[] = { 152e063ecccSJonas Devlieghere { 153e063ecccSJonas Devlieghere eStopShowColumnAnsiOrCaret, 154e063ecccSJonas Devlieghere "ansi-or-caret", 155e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when color/ANSI " 156e063ecccSJonas Devlieghere "mode is enabled; otherwise, fall back to using a text-only caret (^) " 157e063ecccSJonas Devlieghere "as if \"caret-only\" mode was selected.", 158e063ecccSJonas Devlieghere }, 159e063ecccSJonas Devlieghere { 160e063ecccSJonas Devlieghere eStopShowColumnAnsi, 161e063ecccSJonas Devlieghere "ansi", 162e063ecccSJonas Devlieghere "Highlight the stop column with ANSI terminal codes when running LLDB " 163e063ecccSJonas Devlieghere "with color/ANSI enabled.", 164e063ecccSJonas Devlieghere }, 165e063ecccSJonas Devlieghere { 166e063ecccSJonas Devlieghere eStopShowColumnCaret, 167e063ecccSJonas Devlieghere "caret", 168e063ecccSJonas Devlieghere "Highlight the stop column with a caret character (^) underneath the " 169e063ecccSJonas Devlieghere "stop column. This method introduces a new line in source listings " 170e063ecccSJonas Devlieghere "that display thread stop locations.", 171e063ecccSJonas Devlieghere }, 172e063ecccSJonas Devlieghere { 173e063ecccSJonas Devlieghere eStopShowColumnNone, 174e063ecccSJonas Devlieghere "none", 175e063ecccSJonas Devlieghere "Do not highlight the stop column.", 176e063ecccSJonas Devlieghere }, 177e063ecccSJonas Devlieghere }; 1789666ba75STodd Fiala 179971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger 1806a253d37SJordan Rupprecht #include "CoreProperties.inc" 18167cc0636SGreg Clayton 182b9c1b51eSKate Stone enum { 183971f9ca6SJonas Devlieghere #define LLDB_PROPERTIES_debugger 1846a253d37SJordan Rupprecht #include "CorePropertiesEnum.inc" 18567cc0636SGreg Clayton }; 18667cc0636SGreg Clayton 187df370550SEugene Zelenko LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr; 1884c05410fSGreg Clayton 18997206d57SZachary Turner Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, 1904c05410fSGreg Clayton VarSetOperationType op, 19197206d57SZachary Turner llvm::StringRef property_path, 19297206d57SZachary Turner llvm::StringRef value) { 193e063ecccSJonas Devlieghere bool is_load_script = 194e063ecccSJonas Devlieghere (property_path == "target.load-script-from-symbol-file"); 195e5814d78SRaphael Isemann // These properties might change how we visualize data. 196e5814d78SRaphael Isemann bool invalidate_data_vis = (property_path == "escape-non-printables"); 197e5814d78SRaphael Isemann invalidate_data_vis |= 198e5814d78SRaphael Isemann (property_path == "target.max-zero-padding-in-float-format"); 199e5814d78SRaphael Isemann if (invalidate_data_vis) { 200e5814d78SRaphael Isemann DataVisualization::ForceUpdate(); 201e5814d78SRaphael Isemann } 202e5814d78SRaphael Isemann 20384a53dfbSEnrico Granata TargetSP target_sp; 204397ddd5fSEnrico Granata LoadScriptFromSymFile load_script_old_value; 205b9c1b51eSKate Stone if (is_load_script && exe_ctx->GetTargetSP()) { 20684a53dfbSEnrico Granata target_sp = exe_ctx->GetTargetSP(); 207b9c1b51eSKate Stone load_script_old_value = 208b9c1b51eSKate Stone target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); 20984a53dfbSEnrico Granata } 21097206d57SZachary Turner Status error(Properties::SetPropertyValue(exe_ctx, op, property_path, value)); 211b9c1b51eSKate Stone if (error.Success()) { 21284a53dfbSEnrico Granata // FIXME it would be nice to have "on-change" callbacks for properties 213a8ea5955SJonas Devlieghere if (property_path == g_debugger_properties[ePropertyPrompt].name) { 214514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 2154b3c0fd5SJonas Devlieghere std::string str = lldb_private::ansi::FormatAnsiTerminalCodes( 216b9c1b51eSKate Stone new_prompt, GetUseColor()); 217c3ce7f27SMichael Sartain if (str.length()) 218771ef6d4SMalcolm Parsons new_prompt = str; 21944d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 220a8f3ae7cSJonas Devlieghere auto bytes = std::make_unique<EventDataBytes>(new_prompt); 2212f3df613SZachary Turner auto prompt_change_event_sp = std::make_shared<Event>( 2222f3df613SZachary Turner CommandInterpreter::eBroadcastBitResetPrompt, bytes.release()); 2234c05410fSGreg Clayton GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp); 224a8ea5955SJonas Devlieghere } else if (property_path == g_debugger_properties[ePropertyUseColor].name) { 225b9c1b51eSKate Stone // use-color changed. Ping the prompt so it can reset the ansi terminal 226b9c1b51eSKate Stone // codes. 227c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 228acae69d0SEmre Kultursay } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) { 229acae69d0SEmre Kultursay // use-source-cache changed. Wipe out the cache contents if it was disabled. 230acae69d0SEmre Kultursay if (!GetUseSourceCache()) { 231acae69d0SEmre Kultursay m_source_file_cache.Clear(); 232acae69d0SEmre Kultursay } 233b9c1b51eSKate Stone } else if (is_load_script && target_sp && 234b9c1b51eSKate Stone load_script_old_value == eLoadScriptFromSymFileWarn) { 235b9c1b51eSKate Stone if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == 236b9c1b51eSKate Stone eLoadScriptFromSymFileTrue) { 23797206d57SZachary Turner std::list<Status> errors; 2389730339bSEnrico Granata StreamString feedback_stream; 239b9c1b51eSKate Stone if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { 2407ca15ba7SLawrence D'Anna Stream &s = GetErrorStream(); 241b9c1b51eSKate Stone for (auto error : errors) { 2427ca15ba7SLawrence D'Anna s.Printf("%s\n", error.AsCString()); 24384a53dfbSEnrico Granata } 2449730339bSEnrico Granata if (feedback_stream.GetSize()) 2457ca15ba7SLawrence D'Anna s.PutCString(feedback_stream.GetString()); 24684a53dfbSEnrico Granata } 24784a53dfbSEnrico Granata } 248ebdc1ac0SEnrico Granata } 2494c05410fSGreg Clayton } 2504c05410fSGreg Clayton return error; 2514c05410fSGreg Clayton } 2524c05410fSGreg Clayton 253b9c1b51eSKate Stone bool Debugger::GetAutoConfirm() const { 25467cc0636SGreg Clayton const uint32_t idx = ePropertyAutoConfirm; 255b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 256a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 25767cc0636SGreg Clayton } 25867cc0636SGreg Clayton 259b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { 260aff1b357SJason Molenda const uint32_t idx = ePropertyDisassemblyFormat; 261df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 262aff1b357SJason Molenda } 263aff1b357SJason Molenda 264b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetFrameFormat() const { 26567cc0636SGreg Clayton const uint32_t idx = ePropertyFrameFormat; 266df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 26767cc0636SGreg Clayton } 26867cc0636SGreg Clayton 2697f1c1211SPavel Labath const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { 2707f1c1211SPavel Labath const uint32_t idx = ePropertyFrameFormatUnique; 2717f1c1211SPavel Labath return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 2727f1c1211SPavel Labath } 2737f1c1211SPavel Labath 274b889ef42SMed Ismail Bennani uint32_t Debugger::GetStopDisassemblyMaxSize() const { 275b889ef42SMed Ismail Bennani const uint32_t idx = ePropertyStopDisassemblyMaxSize; 276b889ef42SMed Ismail Bennani return m_collection_sp->GetPropertyAtIndexAsUInt64( 277b889ef42SMed Ismail Bennani nullptr, idx, g_debugger_properties[idx].default_uint_value); 278b889ef42SMed Ismail Bennani } 279b889ef42SMed Ismail Bennani 280b9c1b51eSKate Stone bool Debugger::GetNotifyVoid() const { 28167cc0636SGreg Clayton const uint32_t idx = ePropertyNotiftVoid; 282b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 283a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 28467cc0636SGreg Clayton } 28567cc0636SGreg Clayton 286514d8cd8SZachary Turner llvm::StringRef Debugger::GetPrompt() const { 28767cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 288b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsString( 289a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_cstr_value); 29067cc0636SGreg Clayton } 29167cc0636SGreg Clayton 292514d8cd8SZachary Turner void Debugger::SetPrompt(llvm::StringRef p) { 29367cc0636SGreg Clayton const uint32_t idx = ePropertyPrompt; 294df370550SEugene Zelenko m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); 295514d8cd8SZachary Turner llvm::StringRef new_prompt = GetPrompt(); 296b9c1b51eSKate Stone std::string str = 2974b3c0fd5SJonas Devlieghere lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); 298c3ce7f27SMichael Sartain if (str.length()) 299771ef6d4SMalcolm Parsons new_prompt = str; 30044d93782SGreg Clayton GetCommandInterpreter().UpdatePrompt(new_prompt); 30167cc0636SGreg Clayton } 30267cc0636SGreg Clayton 3039e046f02SJonas Devlieghere llvm::StringRef Debugger::GetReproducerPath() const { 3049e046f02SJonas Devlieghere auto &r = repro::Reproducer::Instance(); 3059e046f02SJonas Devlieghere return r.GetReproducerPath().GetCString(); 3069e046f02SJonas Devlieghere } 3079e046f02SJonas Devlieghere 308b9c1b51eSKate Stone const FormatEntity::Entry *Debugger::GetThreadFormat() const { 30967cc0636SGreg Clayton const uint32_t idx = ePropertyThreadFormat; 310df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 31167cc0636SGreg Clayton } 31267cc0636SGreg Clayton 3136a9767c7SJim Ingham const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { 3146a9767c7SJim Ingham const uint32_t idx = ePropertyThreadStopFormat; 3156a9767c7SJim Ingham return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); 3166a9767c7SJim Ingham } 3176a9767c7SJim Ingham 318b9c1b51eSKate Stone lldb::ScriptLanguage Debugger::GetScriptLanguage() const { 31967cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 320b9c1b51eSKate Stone return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( 321a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 32267cc0636SGreg Clayton } 32367cc0636SGreg Clayton 324b9c1b51eSKate Stone bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { 32567cc0636SGreg Clayton const uint32_t idx = ePropertyScriptLanguage; 326b9c1b51eSKate Stone return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, 327b9c1b51eSKate Stone script_lang); 32867cc0636SGreg Clayton } 32967cc0636SGreg Clayton 33046a28a95SJonas Devlieghere lldb::LanguageType Debugger::GetREPLLanguage() const { 33146a28a95SJonas Devlieghere const uint32_t idx = ePropertyREPLLanguage; 33246a28a95SJonas Devlieghere OptionValueLanguage *value = 33346a28a95SJonas Devlieghere m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, idx); 33446a28a95SJonas Devlieghere if (value) 33546a28a95SJonas Devlieghere return value->GetCurrentValue(); 33646a28a95SJonas Devlieghere return LanguageType(); 33746a28a95SJonas Devlieghere } 33846a28a95SJonas Devlieghere 33946a28a95SJonas Devlieghere bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) { 34046a28a95SJonas Devlieghere const uint32_t idx = ePropertyREPLLanguage; 34146a28a95SJonas Devlieghere return m_collection_sp->SetPropertyAtIndexAsLanguage(nullptr, idx, repl_lang); 34246a28a95SJonas Devlieghere } 34346a28a95SJonas Devlieghere 344b9c1b51eSKate Stone uint32_t Debugger::GetTerminalWidth() const { 34567cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 346b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 347a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 34867cc0636SGreg Clayton } 34967cc0636SGreg Clayton 350b9c1b51eSKate Stone bool Debugger::SetTerminalWidth(uint32_t term_width) { 351d9166ad2SFred Riss if (auto handler_sp = m_io_handler_stack.Top()) 352d9166ad2SFred Riss handler_sp->TerminalSizeChanged(); 353d9166ad2SFred Riss 35467cc0636SGreg Clayton const uint32_t idx = ePropertyTerminalWidth; 355df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); 35667cc0636SGreg Clayton } 35767cc0636SGreg Clayton 358b9c1b51eSKate Stone bool Debugger::GetUseExternalEditor() const { 35967cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 360b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 361a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 36267cc0636SGreg Clayton } 36367cc0636SGreg Clayton 364b9c1b51eSKate Stone bool Debugger::SetUseExternalEditor(bool b) { 36567cc0636SGreg Clayton const uint32_t idx = ePropertyUseExternalEditor; 366df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 36767cc0636SGreg Clayton } 36867cc0636SGreg Clayton 369b9c1b51eSKate Stone bool Debugger::GetUseColor() const { 370c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 371b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsBoolean( 372a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 373c3ce7f27SMichael Sartain } 374c3ce7f27SMichael Sartain 375b9c1b51eSKate Stone bool Debugger::SetUseColor(bool b) { 376c3ce7f27SMichael Sartain const uint32_t idx = ePropertyUseColor; 377df370550SEugene Zelenko bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 378c3ce7f27SMichael Sartain SetPrompt(GetPrompt()); 379c3ce7f27SMichael Sartain return ret; 380c3ce7f27SMichael Sartain } 381c3ce7f27SMichael Sartain 3825a27b998SJonas Devlieghere bool Debugger::GetShowProgress() const { 3835a27b998SJonas Devlieghere const uint32_t idx = ePropertyShowProgress; 3845a27b998SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsBoolean( 3855a27b998SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 3865a27b998SJonas Devlieghere } 3875a27b998SJonas Devlieghere 388097d46f4SJonas Devlieghere llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const { 389097d46f4SJonas Devlieghere const uint32_t idx = ePropertyShowProgressAnsiPrefix; 390097d46f4SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 391097d46f4SJonas Devlieghere } 392097d46f4SJonas Devlieghere 393097d46f4SJonas Devlieghere llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const { 394097d46f4SJonas Devlieghere const uint32_t idx = ePropertyShowProgressAnsiSuffix; 395097d46f4SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 396097d46f4SJonas Devlieghere } 397097d46f4SJonas Devlieghere 398de9e8502SShu Anzai bool Debugger::GetUseAutosuggestion() const { 399de9e8502SShu Anzai const uint32_t idx = ePropertyShowAutosuggestion; 400de9e8502SShu Anzai return m_collection_sp->GetPropertyAtIndexAsBoolean( 401de9e8502SShu Anzai nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 402de9e8502SShu Anzai } 403de9e8502SShu Anzai 404080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const { 405080635efSJonas Devlieghere const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix; 406080635efSJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 407080635efSJonas Devlieghere } 408080635efSJonas Devlieghere 409080635efSJonas Devlieghere llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const { 410080635efSJonas Devlieghere const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix; 411080635efSJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 412080635efSJonas Devlieghere } 413080635efSJonas Devlieghere 414acae69d0SEmre Kultursay bool Debugger::GetUseSourceCache() const { 415acae69d0SEmre Kultursay const uint32_t idx = ePropertyUseSourceCache; 416acae69d0SEmre Kultursay return m_collection_sp->GetPropertyAtIndexAsBoolean( 417acae69d0SEmre Kultursay nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); 418acae69d0SEmre Kultursay } 419acae69d0SEmre Kultursay 420acae69d0SEmre Kultursay bool Debugger::SetUseSourceCache(bool b) { 421acae69d0SEmre Kultursay const uint32_t idx = ePropertyUseSourceCache; 422acae69d0SEmre Kultursay bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 423acae69d0SEmre Kultursay if (!ret) { 424acae69d0SEmre Kultursay m_source_file_cache.Clear(); 425acae69d0SEmre Kultursay } 426acae69d0SEmre Kultursay return ret; 427acae69d0SEmre Kultursay } 428566afa0aSRaphael Isemann bool Debugger::GetHighlightSource() const { 429566afa0aSRaphael Isemann const uint32_t idx = ePropertyHighlightSource; 430566afa0aSRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsBoolean( 431a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 432566afa0aSRaphael Isemann } 433566afa0aSRaphael Isemann 4349666ba75STodd Fiala StopShowColumn Debugger::GetStopShowColumn() const { 4359666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumn; 4369666ba75STodd Fiala return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( 437a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 4389666ba75STodd Fiala } 4399666ba75STodd Fiala 44020786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const { 4419666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiPrefix; 44220786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4439666ba75STodd Fiala } 4449666ba75STodd Fiala 44520786326SRaphael Isemann llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const { 4469666ba75STodd Fiala const uint32_t idx = ePropertyStopShowColumnAnsiSuffix; 44720786326SRaphael Isemann return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 4489666ba75STodd Fiala } 4499666ba75STodd Fiala 450841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const { 451841be985SJonas Devlieghere const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix; 452841be985SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 453841be985SJonas Devlieghere } 454841be985SJonas Devlieghere 455841be985SJonas Devlieghere llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const { 456841be985SJonas Devlieghere const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix; 457841be985SJonas Devlieghere return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); 458841be985SJonas Devlieghere } 459841be985SJonas Devlieghere 460b9c1b51eSKate Stone uint32_t Debugger::GetStopSourceLineCount(bool before) const { 461b9c1b51eSKate Stone const uint32_t idx = 462b9c1b51eSKate Stone before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; 463b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 464a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 46567cc0636SGreg Clayton } 46667cc0636SGreg Clayton 467b9c1b51eSKate Stone Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { 46867cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyDisplay; 469b9c1b51eSKate Stone return (Debugger::StopDisassemblyType) 470b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsEnumeration( 471a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 47267cc0636SGreg Clayton } 47367cc0636SGreg Clayton 474b9c1b51eSKate Stone uint32_t Debugger::GetDisassemblyLineCount() const { 47567cc0636SGreg Clayton const uint32_t idx = ePropertyStopDisassemblyCount; 476b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsSInt64( 477a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 47867cc0636SGreg Clayton } 479e372b98dSGreg Clayton 480b9c1b51eSKate Stone bool Debugger::GetAutoOneLineSummaries() const { 48190a8db30SEnrico Granata const uint32_t idx = ePropertyAutoOneLineSummaries; 482df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 483ebdc1ac0SEnrico Granata } 484553fad5cSEnrico Granata 485b9c1b51eSKate Stone bool Debugger::GetEscapeNonPrintables() const { 486ebdc1ac0SEnrico Granata const uint32_t idx = ePropertyEscapeNonPrintables; 487df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 488553fad5cSEnrico Granata } 489553fad5cSEnrico Granata 490b9c1b51eSKate Stone bool Debugger::GetAutoIndent() const { 4916681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 492df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 4936681041dSSean Callanan } 4946681041dSSean Callanan 495b9c1b51eSKate Stone bool Debugger::SetAutoIndent(bool b) { 4966681041dSSean Callanan const uint32_t idx = ePropertyAutoIndent; 497df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 4986681041dSSean Callanan } 4996681041dSSean Callanan 500b9c1b51eSKate Stone bool Debugger::GetPrintDecls() const { 5016681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 502df370550SEugene Zelenko return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); 5036681041dSSean Callanan } 5046681041dSSean Callanan 505b9c1b51eSKate Stone bool Debugger::SetPrintDecls(bool b) { 5066681041dSSean Callanan const uint32_t idx = ePropertyPrintDecls; 507df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); 5086681041dSSean Callanan } 5096681041dSSean Callanan 510b9c1b51eSKate Stone uint32_t Debugger::GetTabSize() const { 5116681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 512b9c1b51eSKate Stone return m_collection_sp->GetPropertyAtIndexAsUInt64( 513a8ea5955SJonas Devlieghere nullptr, idx, g_debugger_properties[idx].default_uint_value); 5146681041dSSean Callanan } 5156681041dSSean Callanan 516b9c1b51eSKate Stone bool Debugger::SetTabSize(uint32_t tab_size) { 5176681041dSSean Callanan const uint32_t idx = ePropertyTabSize; 518df370550SEugene Zelenko return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); 5196681041dSSean Callanan } 5206681041dSSean Callanan 5211b654882SGreg Clayton #pragma mark Debugger 5221b654882SGreg Clayton 52367cc0636SGreg Clayton // const DebuggerPropertiesSP & 52467cc0636SGreg Clayton // Debugger::GetSettings() const 52567cc0636SGreg Clayton //{ 52667cc0636SGreg Clayton // return m_properties_sp; 52767cc0636SGreg Clayton //} 52867cc0636SGreg Clayton // 52999d0faf2SGreg Clayton 530b9c1b51eSKate Stone void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) { 531b9c1b51eSKate Stone assert(g_debugger_list_ptr == nullptr && 532b9c1b51eSKate Stone "Debugger::Initialize called more than once!"); 5336c42e063SGreg Clayton g_debugger_list_mutex_ptr = new std::recursive_mutex(); 5346c42e063SGreg Clayton g_debugger_list_ptr = new DebuggerList(); 5355fb8f797SGreg Clayton g_load_plugin_callback = load_plugin_callback; 53699d0faf2SGreg Clayton } 53730fdc8d8SChris Lattner 538b9c1b51eSKate Stone void Debugger::Terminate() { 539b9c1b51eSKate Stone assert(g_debugger_list_ptr && 540b9c1b51eSKate Stone "Debugger::Terminate called without a matching Debugger::Initialize!"); 541e6e2bb38SZachary Turner 542b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 54395af9d88SQuinn Pham // Clear our global list of debugger objects 5446c42e063SGreg Clayton { 5456c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 5466c42e063SGreg Clayton for (const auto &debugger : *g_debugger_list_ptr) 547f3cd1819SOleksiy Vyalov debugger->Clear(); 5486c42e063SGreg Clayton g_debugger_list_ptr->clear(); 5496c42e063SGreg Clayton } 5506c42e063SGreg Clayton } 55130fdc8d8SChris Lattner } 55230fdc8d8SChris Lattner 553b9c1b51eSKate Stone void Debugger::SettingsInitialize() { Target::SettingsInitialize(); } 55420bd37f7SCaroline Tice 555b9c1b51eSKate Stone void Debugger::SettingsTerminate() { Target::SettingsTerminate(); } 55620bd37f7SCaroline Tice 55797206d57SZachary Turner bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) { 558b9c1b51eSKate Stone if (g_load_plugin_callback) { 559b9c1b51eSKate Stone llvm::sys::DynamicLibrary dynlib = 560b9c1b51eSKate Stone g_load_plugin_callback(shared_from_this(), spec, error); 561b9c1b51eSKate Stone if (dynlib.isValid()) { 56258a559c0SZachary Turner m_loaded_plugins.push_back(dynlib); 56321dfcd9dSEnrico Granata return true; 56421dfcd9dSEnrico Granata } 565b9c1b51eSKate Stone } else { 56605097246SAdrian Prantl // The g_load_plugin_callback is registered in SBDebugger::Initialize() and 56705097246SAdrian Prantl // if the public API layer isn't available (code is linking against all of 56805097246SAdrian Prantl // the internal LLDB static libraries), then we can't load plugins 5695fb8f797SGreg Clayton error.SetErrorString("Public API layer is not available"); 5705fb8f797SGreg Clayton } 57121dfcd9dSEnrico Granata return false; 57221dfcd9dSEnrico Granata } 57321dfcd9dSEnrico Granata 57435e4c84cSJonas Devlieghere static FileSystem::EnumerateDirectoryResult 5757d86ee5aSZachary Turner LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, 57635e4c84cSJonas Devlieghere llvm::StringRef path) { 57797206d57SZachary Turner Status error; 57821dfcd9dSEnrico Granata 579ad8d48f9SJonas Devlieghere static ConstString g_dylibext(".dylib"); 580ad8d48f9SJonas Devlieghere static ConstString g_solibext(".so"); 58121dfcd9dSEnrico Granata 58221dfcd9dSEnrico Granata if (!baton) 58335e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultQuit; 58421dfcd9dSEnrico Granata 58521dfcd9dSEnrico Granata Debugger *debugger = (Debugger *)baton; 58621dfcd9dSEnrico Granata 5877d86ee5aSZachary Turner namespace fs = llvm::sys::fs; 58805097246SAdrian Prantl // If we have a regular file, a symbolic link or unknown file type, try and 58905097246SAdrian Prantl // process the file. We must handle unknown as sometimes the directory 59021dfcd9dSEnrico Granata // enumeration might be enumerating a file system that doesn't have correct 59121dfcd9dSEnrico Granata // file type information. 5927d86ee5aSZachary Turner if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file || 5937d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 5948f3be7a3SJonas Devlieghere FileSpec plugin_file_spec(path); 5958f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(plugin_file_spec); 59621dfcd9dSEnrico Granata 5973cf443ddSMichael Sartain if (plugin_file_spec.GetFileNameExtension() != g_dylibext && 598b9c1b51eSKate Stone plugin_file_spec.GetFileNameExtension() != g_solibext) { 59935e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 6003cf443ddSMichael Sartain } 60121dfcd9dSEnrico Granata 60297206d57SZachary Turner Status plugin_load_error; 603e743c782SEnrico Granata debugger->LoadPlugin(plugin_file_spec, plugin_load_error); 60421dfcd9dSEnrico Granata 60535e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 6067d86ee5aSZachary Turner } else if (ft == fs::file_type::directory_file || 6077d86ee5aSZachary Turner ft == fs::file_type::symlink_file || 6087d86ee5aSZachary Turner ft == fs::file_type::type_unknown) { 60905097246SAdrian Prantl // Try and recurse into anything that a directory or symbolic link. We must 61005097246SAdrian Prantl // also do this for unknown as sometimes the directory enumeration might be 61105097246SAdrian Prantl // enumerating a file system that doesn't have correct file type 61221dfcd9dSEnrico Granata // information. 61335e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultEnter; 61421dfcd9dSEnrico Granata } 61521dfcd9dSEnrico Granata 61635e4c84cSJonas Devlieghere return FileSystem::eEnumerateDirectoryResultNext; 61721dfcd9dSEnrico Granata } 61821dfcd9dSEnrico Granata 619b9c1b51eSKate Stone void Debugger::InstanceInitialize() { 62021dfcd9dSEnrico Granata const bool find_directories = true; 62121dfcd9dSEnrico Granata const bool find_files = true; 62221dfcd9dSEnrico Granata const bool find_other = true; 62321dfcd9dSEnrico Granata char dir_path[PATH_MAX]; 62460f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) { 625dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 626dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 62735e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 62835e4c84cSJonas Devlieghere find_files, find_other, 62935e4c84cSJonas Devlieghere LoadPluginCallback, this); 63021dfcd9dSEnrico Granata } 63121dfcd9dSEnrico Granata } 63221dfcd9dSEnrico Granata 63360f028ffSPavel Labath if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) { 634dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(dir_spec) && 635dbd7fabaSJonas Devlieghere dir_spec.GetPath(dir_path, sizeof(dir_path))) { 63635e4c84cSJonas Devlieghere FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, 63735e4c84cSJonas Devlieghere find_files, find_other, 63835e4c84cSJonas Devlieghere LoadPluginCallback, this); 63921dfcd9dSEnrico Granata } 64021dfcd9dSEnrico Granata } 641e8cd0c98SGreg Clayton 642e8cd0c98SGreg Clayton PluginManager::DebuggerInitialize(*this); 64321dfcd9dSEnrico Granata } 64421dfcd9dSEnrico Granata 645b9c1b51eSKate Stone DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, 646b9c1b51eSKate Stone void *baton) { 647228063cdSJim Ingham DebuggerSP debugger_sp(new Debugger(log_callback, baton)); 648b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6496c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6506c42e063SGreg Clayton g_debugger_list_ptr->push_back(debugger_sp); 6516611103cSGreg Clayton } 65221dfcd9dSEnrico Granata debugger_sp->InstanceInitialize(); 6536611103cSGreg Clayton return debugger_sp; 6546611103cSGreg Clayton } 6556611103cSGreg Clayton 656b9c1b51eSKate Stone void Debugger::Destroy(DebuggerSP &debugger_sp) { 657df370550SEugene Zelenko if (!debugger_sp) 658e02657b1SCaroline Tice return; 659e02657b1SCaroline Tice 660d6b64612SMed Ismail Bennani CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter(); 661d6b64612SMed Ismail Bennani 662d6b64612SMed Ismail Bennani if (cmd_interpreter.GetSaveSessionOnQuit()) { 663d6b64612SMed Ismail Bennani CommandReturnObject result(debugger_sp->GetUseColor()); 664d6b64612SMed Ismail Bennani cmd_interpreter.SaveTranscript(result); 665d6b64612SMed Ismail Bennani if (result.Succeeded()) 666d6b64612SMed Ismail Bennani debugger_sp->GetOutputStream() << result.GetOutputData() << '\n'; 667d6b64612SMed Ismail Bennani else 668d6b64612SMed Ismail Bennani debugger_sp->GetErrorStream() << result.GetErrorData() << '\n'; 669d6b64612SMed Ismail Bennani } 670d6b64612SMed Ismail Bennani 6718314c525SJim Ingham debugger_sp->Clear(); 6728314c525SJim Ingham 673b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6746c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6756c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 676b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 677b9c1b51eSKate Stone if ((*pos).get() == debugger_sp.get()) { 6786c42e063SGreg Clayton g_debugger_list_ptr->erase(pos); 679e02657b1SCaroline Tice return; 680e02657b1SCaroline Tice } 681e02657b1SCaroline Tice } 682e02657b1SCaroline Tice } 683c15f55e2SGreg Clayton } 684e02657b1SCaroline Tice 685e063ecccSJonas Devlieghere DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { 6864d122c40SGreg Clayton DebuggerSP debugger_sp; 687b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 6886c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 6896c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 690b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 691b9c1b51eSKate Stone if ((*pos)->m_instance_name == instance_name) { 6926920b52bSGreg Clayton debugger_sp = *pos; 6936920b52bSGreg Clayton break; 6946920b52bSGreg Clayton } 6956920b52bSGreg Clayton } 6966920b52bSGreg Clayton } 6973df9a8dfSCaroline Tice return debugger_sp; 6983df9a8dfSCaroline Tice } 6996611103cSGreg Clayton 700b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) { 7014d122c40SGreg Clayton TargetSP target_sp; 702b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 7036c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 7046c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 705b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 7066611103cSGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid); 7076611103cSGreg Clayton if (target_sp) 7086611103cSGreg Clayton break; 7096611103cSGreg Clayton } 710c15f55e2SGreg Clayton } 7116611103cSGreg Clayton return target_sp; 7126611103cSGreg Clayton } 7136611103cSGreg Clayton 714b9c1b51eSKate Stone TargetSP Debugger::FindTargetWithProcess(Process *process) { 715e4e45924SGreg Clayton TargetSP target_sp; 716b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 7176c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 7186c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 719b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 720e4e45924SGreg Clayton target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process); 721e4e45924SGreg Clayton if (target_sp) 722e4e45924SGreg Clayton break; 723e4e45924SGreg Clayton } 724c15f55e2SGreg Clayton } 725e4e45924SGreg Clayton return target_sp; 726e4e45924SGreg Clayton } 727e4e45924SGreg Clayton 728e122877fSGreg Clayton ConstString Debugger::GetStaticBroadcasterClass() { 729e122877fSGreg Clayton static ConstString class_name("lldb.debugger"); 730e122877fSGreg Clayton return class_name; 731e122877fSGreg Clayton } 732e122877fSGreg Clayton 733b9c1b51eSKate Stone Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) 734b9c1b51eSKate Stone : UserID(g_unique_id++), 7352f3df613SZachary Turner Properties(std::make_shared<OptionValueProperties>()), 736f913fd6eSLawrence D'Anna m_input_file_sp(std::make_shared<NativeFile>(stdin, false)), 7377ca15ba7SLawrence D'Anna m_output_stream_sp(std::make_shared<StreamFile>(stdout, false)), 7387ca15ba7SLawrence D'Anna m_error_stream_sp(std::make_shared<StreamFile>(stderr, false)), 739d77c2e09SJonas Devlieghere m_input_recorder(nullptr), 740583bbb1dSJim Ingham m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), 741b9c1b51eSKate Stone m_terminal_state(), m_target_list(*this), m_platform_list(), 742583bbb1dSJim Ingham m_listener_sp(Listener::MakeListener("lldb.Debugger")), 743d5b44036SJonas Devlieghere m_source_manager_up(), m_source_file_cache(), 744f20dd1d5SJonas Devlieghere m_command_interpreter_up( 745a8f3ae7cSJonas Devlieghere std::make_unique<CommandInterpreter>(*this, false)), 7467ce2de2cSJonas Devlieghere m_io_handler_stack(), m_instance_name(), m_loaded_plugins(), 747bbf70c04SJonas Devlieghere m_event_handler_thread(), m_io_handler_thread(), 7484329fe42SGreg Clayton m_sync_broadcaster(nullptr, "lldb.debugger.sync"), 749e122877fSGreg Clayton m_broadcaster(m_broadcaster_manager_sp, 750e122877fSGreg Clayton GetStaticBroadcasterClass().AsCString()), 751b9c1b51eSKate Stone m_forward_listener_sp(), m_clear_once() { 752db203e02SRaphael Isemann m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str()); 753228063cdSJim Ingham if (log_callback) 7542f3df613SZachary Turner m_log_callback_stream_sp = 7552f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 756d5b44036SJonas Devlieghere m_command_interpreter_up->Initialize(); 757ded470d3SGreg Clayton // Always add our default platform to the platform list 758615eb7e6SGreg Clayton PlatformSP default_platform_sp(Platform::GetHostPlatform()); 759df370550SEugene Zelenko assert(default_platform_sp); 760ded470d3SGreg Clayton m_platform_list.Append(default_platform_sp, true); 76167cc0636SGreg Clayton 76216e5a347SVedant Kumar // Create the dummy target. 76316e5a347SVedant Kumar { 76416e5a347SVedant Kumar ArchSpec arch(Target::GetDefaultArchitecture()); 76516e5a347SVedant Kumar if (!arch.IsValid()) 76616e5a347SVedant Kumar arch = HostInfo::GetArchitecture(); 76716e5a347SVedant Kumar assert(arch.IsValid() && "No valid default or host archspec"); 76816e5a347SVedant Kumar const bool is_dummy_target = true; 76916e5a347SVedant Kumar m_dummy_target_sp.reset( 77016e5a347SVedant Kumar new Target(*this, arch, default_platform_sp, is_dummy_target)); 77116e5a347SVedant Kumar } 772d43d912bSRaphael Isemann assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?"); 773d43d912bSRaphael Isemann 774a8ea5955SJonas Devlieghere m_collection_sp->Initialize(g_debugger_properties); 775b9c1b51eSKate Stone m_collection_sp->AppendProperty( 776b9c1b51eSKate Stone ConstString("target"), 777b9c1b51eSKate Stone ConstString("Settings specify to debugging targets."), true, 7783d7161e3SPavel Labath Target::GetGlobalProperties().GetValueProperties()); 779b9c1b51eSKate Stone m_collection_sp->AppendProperty( 780b9c1b51eSKate Stone ConstString("platform"), ConstString("Platform settings."), true, 7813d7161e3SPavel Labath Platform::GetGlobalPlatformProperties().GetValueProperties()); 782235354beSAdrian Prantl m_collection_sp->AppendProperty( 7833cd29bcfSAdrian Prantl ConstString("symbols"), ConstString("Symbol lookup and cache settings."), 7843cd29bcfSAdrian Prantl true, ModuleList::GetGlobalModuleListProperties().GetValueProperties()); 785d5b44036SJonas Devlieghere if (m_command_interpreter_up) { 786b9c1b51eSKate Stone m_collection_sp->AppendProperty( 787b9c1b51eSKate Stone ConstString("interpreter"), 788754a9369SGreg Clayton ConstString("Settings specify to the debugger's command interpreter."), 789d5b44036SJonas Devlieghere true, m_command_interpreter_up->GetValueProperties()); 790754a9369SGreg Clayton } 791b9c1b51eSKate Stone OptionValueSInt64 *term_width = 792b9c1b51eSKate Stone m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64( 793b9c1b51eSKate Stone nullptr, ePropertyTerminalWidth); 79467cc0636SGreg Clayton term_width->SetMinimumValue(10); 79567cc0636SGreg Clayton term_width->SetMaximumValue(1024); 796c3ce7f27SMichael Sartain 797c3ce7f27SMichael Sartain // Turn off use-color if this is a dumb terminal. 798c3ce7f27SMichael Sartain const char *term = getenv("TERM"); 799c3ce7f27SMichael Sartain if (term && !strcmp(term, "dumb")) 800c3ce7f27SMichael Sartain SetUseColor(false); 801eca9ce14SRaphael Isemann // Turn off use-color if we don't write to a terminal with color support. 8027ca15ba7SLawrence D'Anna if (!GetOutputFile().GetIsTerminalWithColors()) 803eca9ce14SRaphael Isemann SetUseColor(false); 8048aa23614SDavid Bolvansky 8058aa23614SDavid Bolvansky #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) 8068aa23614SDavid Bolvansky // Enabling use of ANSI color codes because LLDB is using them to highlight 8078aa23614SDavid Bolvansky // text. 8088aa23614SDavid Bolvansky llvm::sys::Process::UseANSIEscapeCodes(true); 8098aa23614SDavid Bolvansky #endif 81030fdc8d8SChris Lattner } 81130fdc8d8SChris Lattner 812b9c1b51eSKate Stone Debugger::~Debugger() { Clear(); } 8138314c525SJim Ingham 814b9c1b51eSKate Stone void Debugger::Clear() { 81505097246SAdrian Prantl // Make sure we call this function only once. With the C++ global destructor 81605097246SAdrian Prantl // chain having a list of debuggers and with code that can be running on 81705097246SAdrian Prantl // other threads, we need to ensure this doesn't happen multiple times. 8184329fe42SGreg Clayton // 8194329fe42SGreg Clayton // The following functions call Debugger::Clear(): 8204329fe42SGreg Clayton // Debugger::~Debugger(); 8214329fe42SGreg Clayton // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp); 8224329fe42SGreg Clayton // static void Debugger::Terminate(); 823c5f28e2aSKamil Rytarowski llvm::call_once(m_clear_once, [this]() { 82444d93782SGreg Clayton ClearIOHandlers(); 82544d93782SGreg Clayton StopIOHandlerThread(); 82644d93782SGreg Clayton StopEventHandlerThread(); 827583bbb1dSJim Ingham m_listener_sp->Clear(); 828de448c0aSJonas Devlieghere for (TargetSP target_sp : m_target_list.Targets()) { 829b9c1b51eSKate Stone if (target_sp) { 830de448c0aSJonas Devlieghere if (ProcessSP process_sp = target_sp->GetProcessSP()) 8311fd07059SJim Ingham process_sp->Finalize(); 832ccbc08e6SGreg Clayton target_sp->Destroy(); 8336611103cSGreg Clayton } 83430fdc8d8SChris Lattner } 835583bbb1dSJim Ingham m_broadcaster_manager_sp->Clear(); 83630fdc8d8SChris Lattner 837b9c1b51eSKate Stone // Close the input file _before_ we close the input read communications 83805097246SAdrian Prantl // class as it does NOT own the input file, our m_input_file does. 839c5917d9aSJim Ingham m_terminal_state.Clear(); 8407ca15ba7SLawrence D'Anna GetInputFile().Close(); 8410c4129f2SGreg Clayton 842d5b44036SJonas Devlieghere m_command_interpreter_up->Clear(); 8434329fe42SGreg Clayton }); 8448314c525SJim Ingham } 84530fdc8d8SChris Lattner 846b9c1b51eSKate Stone bool Debugger::GetCloseInputOnEOF() const { 84744d93782SGreg Clayton // return m_input_comm.GetCloseOnEOF(); 84844d93782SGreg Clayton return false; 849fc3f027dSGreg Clayton } 850fc3f027dSGreg Clayton 851b9c1b51eSKate Stone void Debugger::SetCloseInputOnEOF(bool b) { 85244d93782SGreg Clayton // m_input_comm.SetCloseOnEOF(b); 853fc3f027dSGreg Clayton } 854fc3f027dSGreg Clayton 855b9c1b51eSKate Stone bool Debugger::GetAsyncExecution() { 856d5b44036SJonas Devlieghere return !m_command_interpreter_up->GetSynchronous(); 85730fdc8d8SChris Lattner } 85830fdc8d8SChris Lattner 859b9c1b51eSKate Stone void Debugger::SetAsyncExecution(bool async_execution) { 860d5b44036SJonas Devlieghere m_command_interpreter_up->SetSynchronous(!async_execution); 86130fdc8d8SChris Lattner } 86230fdc8d8SChris Lattner 863d77c2e09SJonas Devlieghere repro::DataRecorder *Debugger::GetInputRecorder() { return m_input_recorder; } 864d77c2e09SJonas Devlieghere 865f23b829aSLevon Ter-Grigoryan static inline int OpenPipe(int fds[2], std::size_t size) { 866f23b829aSLevon Ter-Grigoryan #ifdef _WIN32 867f23b829aSLevon Ter-Grigoryan return _pipe(fds, size, O_BINARY); 868f23b829aSLevon Ter-Grigoryan #else 869f23b829aSLevon Ter-Grigoryan (void)size; 870f23b829aSLevon Ter-Grigoryan return pipe(fds); 871f23b829aSLevon Ter-Grigoryan #endif 872f23b829aSLevon Ter-Grigoryan } 873f23b829aSLevon Ter-Grigoryan 874f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputString(const char *data) { 875f23b829aSLevon Ter-Grigoryan Status result; 876f23b829aSLevon Ter-Grigoryan enum PIPES { READ, WRITE }; // Indexes for the read and write fds 877f23b829aSLevon Ter-Grigoryan int fds[2] = {-1, -1}; 878f23b829aSLevon Ter-Grigoryan 879f23b829aSLevon Ter-Grigoryan if (data == nullptr) { 880f23b829aSLevon Ter-Grigoryan result.SetErrorString("String data is null"); 881f23b829aSLevon Ter-Grigoryan return result; 882f23b829aSLevon Ter-Grigoryan } 883f23b829aSLevon Ter-Grigoryan 884f23b829aSLevon Ter-Grigoryan size_t size = strlen(data); 885f23b829aSLevon Ter-Grigoryan if (size == 0) { 886f23b829aSLevon Ter-Grigoryan result.SetErrorString("String data is empty"); 887f23b829aSLevon Ter-Grigoryan return result; 888f23b829aSLevon Ter-Grigoryan } 889f23b829aSLevon Ter-Grigoryan 890f23b829aSLevon Ter-Grigoryan if (OpenPipe(fds, size) != 0) { 891f23b829aSLevon Ter-Grigoryan result.SetErrorString( 892f23b829aSLevon Ter-Grigoryan "can't create pipe file descriptors for LLDB commands"); 893f23b829aSLevon Ter-Grigoryan return result; 894f23b829aSLevon Ter-Grigoryan } 895f23b829aSLevon Ter-Grigoryan 896f23b829aSLevon Ter-Grigoryan write(fds[WRITE], data, size); 897f23b829aSLevon Ter-Grigoryan // Close the write end of the pipe, so that the command interpreter will exit 898f23b829aSLevon Ter-Grigoryan // when it consumes all the data. 899f23b829aSLevon Ter-Grigoryan llvm::sys::Process::SafelyCloseFileDescriptor(fds[WRITE]); 900f23b829aSLevon Ter-Grigoryan 901f23b829aSLevon Ter-Grigoryan // Open the read file descriptor as a FILE * that we can return as an input 902f23b829aSLevon Ter-Grigoryan // handle. 903f23b829aSLevon Ter-Grigoryan FILE *commands_file = fdopen(fds[READ], "rb"); 904f23b829aSLevon Ter-Grigoryan if (commands_file == nullptr) { 905f23b829aSLevon Ter-Grigoryan result.SetErrorStringWithFormat("fdopen(%i, \"rb\") failed (errno = %i) " 906f23b829aSLevon Ter-Grigoryan "when trying to open LLDB commands pipe", 907f23b829aSLevon Ter-Grigoryan fds[READ], errno); 908f23b829aSLevon Ter-Grigoryan llvm::sys::Process::SafelyCloseFileDescriptor(fds[READ]); 909f23b829aSLevon Ter-Grigoryan return result; 910f23b829aSLevon Ter-Grigoryan } 911f23b829aSLevon Ter-Grigoryan 912f23b829aSLevon Ter-Grigoryan return SetInputFile( 913f23b829aSLevon Ter-Grigoryan (FileSP)std::make_shared<NativeFile>(commands_file, true)); 914f23b829aSLevon Ter-Grigoryan } 915f23b829aSLevon Ter-Grigoryan 916f23b829aSLevon Ter-Grigoryan Status Debugger::SetInputFile(FileSP file_sp) { 917f23b829aSLevon Ter-Grigoryan Status error; 918f23b829aSLevon Ter-Grigoryan repro::DataRecorder *recorder = nullptr; 919f23b829aSLevon Ter-Grigoryan if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) 920f23b829aSLevon Ter-Grigoryan recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder(); 921f23b829aSLevon Ter-Grigoryan 922f23b829aSLevon Ter-Grigoryan static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader = 923f23b829aSLevon Ter-Grigoryan repro::MultiLoader<repro::CommandProvider>::Create( 924f23b829aSLevon Ter-Grigoryan repro::Reproducer::Instance().GetLoader()); 925f23b829aSLevon Ter-Grigoryan if (loader) { 926f23b829aSLevon Ter-Grigoryan llvm::Optional<std::string> nextfile = loader->GetNextFile(); 927f23b829aSLevon Ter-Grigoryan FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r") 928f23b829aSLevon Ter-Grigoryan : nullptr; 929f23b829aSLevon Ter-Grigoryan // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the 930f23b829aSLevon Ter-Grigoryan // reproducer somehow if fh is NULL? 931f23b829aSLevon Ter-Grigoryan if (fh) { 932f23b829aSLevon Ter-Grigoryan file_sp = std::make_shared<NativeFile>(fh, true); 933f23b829aSLevon Ter-Grigoryan } 934f23b829aSLevon Ter-Grigoryan } 935f23b829aSLevon Ter-Grigoryan 936f23b829aSLevon Ter-Grigoryan if (!file_sp || !file_sp->IsValid()) { 937f23b829aSLevon Ter-Grigoryan error.SetErrorString("invalid file"); 938f23b829aSLevon Ter-Grigoryan return error; 939f23b829aSLevon Ter-Grigoryan } 940f23b829aSLevon Ter-Grigoryan 941f23b829aSLevon Ter-Grigoryan SetInputFile(file_sp, recorder); 942f23b829aSLevon Ter-Grigoryan return error; 943f23b829aSLevon Ter-Grigoryan } 944f23b829aSLevon Ter-Grigoryan 94596898eb6SLawrence D'Anna void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) { 94696898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 947d77c2e09SJonas Devlieghere m_input_recorder = recorder; 948c4701c9cSJonas Devlieghere m_input_file_sp = std::move(file_sp); 94905097246SAdrian Prantl // Save away the terminal state if that is relevant, so that we can restore 95005097246SAdrian Prantl // it in RestoreInputState. 951c5917d9aSJim Ingham SaveInputTerminalState(); 95230fdc8d8SChris Lattner } 95330fdc8d8SChris Lattner 95496898eb6SLawrence D'Anna void Debugger::SetOutputFile(FileSP file_sp) { 95596898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 9567ca15ba7SLawrence D'Anna m_output_stream_sp = std::make_shared<StreamFile>(file_sp); 95730fdc8d8SChris Lattner } 95830fdc8d8SChris Lattner 95996898eb6SLawrence D'Anna void Debugger::SetErrorFile(FileSP file_sp) { 96096898eb6SLawrence D'Anna assert(file_sp && file_sp->IsValid()); 9617ca15ba7SLawrence D'Anna m_error_stream_sp = std::make_shared<StreamFile>(file_sp); 96230fdc8d8SChris Lattner } 96330fdc8d8SChris Lattner 964b9c1b51eSKate Stone void Debugger::SaveInputTerminalState() { 9657ca15ba7SLawrence D'Anna int fd = GetInputFile().GetDescriptor(); 9667ca15ba7SLawrence D'Anna if (fd != File::kInvalidDescriptor) 9677ca15ba7SLawrence D'Anna m_terminal_state.Save(fd, true); 96844d93782SGreg Clayton } 969c5917d9aSJim Ingham 970b9c1b51eSKate Stone void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } 971c5917d9aSJim Ingham 972b9c1b51eSKate Stone ExecutionContext Debugger::GetSelectedExecutionContext() { 973a39bcbcaSTatyana Krasnukha bool adopt_selected = true; 974a39bcbcaSTatyana Krasnukha ExecutionContextRef exe_ctx_ref(GetSelectedTarget().get(), adopt_selected); 975a39bcbcaSTatyana Krasnukha return ExecutionContext(exe_ctx_ref); 97630fdc8d8SChris Lattner } 97730fdc8d8SChris Lattner 978b9c1b51eSKate Stone void Debugger::DispatchInputInterrupt() { 9797ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 9807ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 981efed6131SCaroline Tice if (reader_sp) 98244d93782SGreg Clayton reader_sp->Interrupt(); 983efed6131SCaroline Tice } 984efed6131SCaroline Tice 985b9c1b51eSKate Stone void Debugger::DispatchInputEndOfFile() { 9867ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 9877ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 988efed6131SCaroline Tice if (reader_sp) 98944d93782SGreg Clayton reader_sp->GotEOF(); 990efed6131SCaroline Tice } 991efed6131SCaroline Tice 992b9c1b51eSKate Stone void Debugger::ClearIOHandlers() { 993b9c1b51eSKate Stone // The bottom input reader should be the main debugger input reader. We do 994b9c1b51eSKate Stone // not want to close that one here. 9957ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 9967ce2de2cSJonas Devlieghere while (m_io_handler_stack.GetSize() > 1) { 9977ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 9983d6086f6SCaroline Tice if (reader_sp) 9994446487dSPavel Labath PopIOHandler(reader_sp); 10003d6086f6SCaroline Tice } 10013d6086f6SCaroline Tice } 10023d6086f6SCaroline Tice 10032671df9bSJonas Devlieghere void Debugger::RunIOHandlers() { 100404de24e6SJonas Devlieghere IOHandlerSP reader_sp = m_io_handler_stack.Top(); 1005b9c1b51eSKate Stone while (true) { 100630fdc8d8SChris Lattner if (!reader_sp) 100730fdc8d8SChris Lattner break; 100830fdc8d8SChris Lattner 100944d93782SGreg Clayton reader_sp->Run(); 101004de24e6SJonas Devlieghere { 101104de24e6SJonas Devlieghere std::lock_guard<std::recursive_mutex> guard( 101204de24e6SJonas Devlieghere m_io_handler_synchronous_mutex); 101344d93782SGreg Clayton 101444d93782SGreg Clayton // Remove all input readers that are done from the top of the stack 1015b9c1b51eSKate Stone while (true) { 10167ce2de2cSJonas Devlieghere IOHandlerSP top_reader_sp = m_io_handler_stack.Top(); 101744d93782SGreg Clayton if (top_reader_sp && top_reader_sp->GetIsDone()) 10184446487dSPavel Labath PopIOHandler(top_reader_sp); 101930fdc8d8SChris Lattner else 102030fdc8d8SChris Lattner break; 102130fdc8d8SChris Lattner } 102204de24e6SJonas Devlieghere reader_sp = m_io_handler_stack.Top(); 102304de24e6SJonas Devlieghere } 102430fdc8d8SChris Lattner } 102544d93782SGreg Clayton ClearIOHandlers(); 102644d93782SGreg Clayton } 102730fdc8d8SChris Lattner 102804de24e6SJonas Devlieghere void Debugger::RunIOHandlerSync(const IOHandlerSP &reader_sp) { 102904de24e6SJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_synchronous_mutex); 103004de24e6SJonas Devlieghere 103104de24e6SJonas Devlieghere PushIOHandler(reader_sp); 103204de24e6SJonas Devlieghere IOHandlerSP top_reader_sp = reader_sp; 103304de24e6SJonas Devlieghere 103404de24e6SJonas Devlieghere while (top_reader_sp) { 103504de24e6SJonas Devlieghere if (!top_reader_sp) 103604de24e6SJonas Devlieghere break; 103704de24e6SJonas Devlieghere 103804de24e6SJonas Devlieghere top_reader_sp->Run(); 103904de24e6SJonas Devlieghere 104004de24e6SJonas Devlieghere // Don't unwind past the starting point. 104104de24e6SJonas Devlieghere if (top_reader_sp.get() == reader_sp.get()) { 104204de24e6SJonas Devlieghere if (PopIOHandler(reader_sp)) 104304de24e6SJonas Devlieghere break; 104404de24e6SJonas Devlieghere } 104504de24e6SJonas Devlieghere 104604de24e6SJonas Devlieghere // If we pushed new IO handlers, pop them if they're done or restart the 104704de24e6SJonas Devlieghere // loop to run them if they're not. 104804de24e6SJonas Devlieghere while (true) { 104904de24e6SJonas Devlieghere top_reader_sp = m_io_handler_stack.Top(); 105004de24e6SJonas Devlieghere if (top_reader_sp && top_reader_sp->GetIsDone()) { 105104de24e6SJonas Devlieghere PopIOHandler(top_reader_sp); 105204de24e6SJonas Devlieghere // Don't unwind past the starting point. 105304de24e6SJonas Devlieghere if (top_reader_sp.get() == reader_sp.get()) 105404de24e6SJonas Devlieghere return; 105504de24e6SJonas Devlieghere } else { 105604de24e6SJonas Devlieghere break; 105704de24e6SJonas Devlieghere } 105804de24e6SJonas Devlieghere } 105904de24e6SJonas Devlieghere } 106004de24e6SJonas Devlieghere } 106104de24e6SJonas Devlieghere 1062b9c1b51eSKate Stone bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) { 10637ce2de2cSJonas Devlieghere return m_io_handler_stack.IsTop(reader_sp); 106444d93782SGreg Clayton } 106530fdc8d8SChris Lattner 1066b9c1b51eSKate Stone bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, 1067b9c1b51eSKate Stone IOHandler::Type second_top_type) { 10687ce2de2cSJonas Devlieghere return m_io_handler_stack.CheckTopIOHandlerTypes(top_type, second_top_type); 10696681041dSSean Callanan } 10706681041dSSean Callanan 1071b9c1b51eSKate Stone void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { 10722436c570SJonas Devlieghere bool printed = m_io_handler_stack.PrintAsync(s, len, is_stdout); 10732436c570SJonas Devlieghere if (!printed) { 10742436c570SJonas Devlieghere lldb::StreamFileSP stream = 10752436c570SJonas Devlieghere is_stdout ? m_output_stream_sp : m_error_stream_sp; 10762436c570SJonas Devlieghere stream->Write(s, len); 10772436c570SJonas Devlieghere } 10784446487dSPavel Labath } 107944d93782SGreg Clayton 1080b9c1b51eSKate Stone ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { 10817ce2de2cSJonas Devlieghere return m_io_handler_stack.GetTopIOHandlerControlSequence(ch); 108230fdc8d8SChris Lattner } 108330fdc8d8SChris Lattner 1084b9c1b51eSKate Stone const char *Debugger::GetIOHandlerCommandPrefix() { 10857ce2de2cSJonas Devlieghere return m_io_handler_stack.GetTopIOHandlerCommandPrefix(); 1086a487aa4cSKate Stone } 1087a487aa4cSKate Stone 1088b9c1b51eSKate Stone const char *Debugger::GetIOHandlerHelpPrologue() { 10897ce2de2cSJonas Devlieghere return m_io_handler_stack.GetTopIOHandlerHelpPrologue(); 1090a487aa4cSKate Stone } 1091a487aa4cSKate Stone 10927ce2de2cSJonas Devlieghere bool Debugger::RemoveIOHandler(const IOHandlerSP &reader_sp) { 10937ce2de2cSJonas Devlieghere return PopIOHandler(reader_sp); 10947ce2de2cSJonas Devlieghere } 10957ce2de2cSJonas Devlieghere 10967ce2de2cSJonas Devlieghere void Debugger::RunIOHandlerAsync(const IOHandlerSP &reader_sp, 10977ce2de2cSJonas Devlieghere bool cancel_top_handler) { 10987ce2de2cSJonas Devlieghere PushIOHandler(reader_sp, cancel_top_handler); 10997ce2de2cSJonas Devlieghere } 11007ce2de2cSJonas Devlieghere 11017ca15ba7SLawrence D'Anna void Debugger::AdoptTopIOHandlerFilesIfInvalid(FileSP &in, StreamFileSP &out, 1102b9c1b51eSKate Stone StreamFileSP &err) { 110305097246SAdrian Prantl // Before an IOHandler runs, it must have in/out/err streams. This function 110405097246SAdrian Prantl // is called when one ore more of the streams are nullptr. We use the top 110505097246SAdrian Prantl // input reader's in/out/err streams, or fall back to the debugger file 110605097246SAdrian Prantl // handles, or we fall back onto stdin/stdout/stderr as a last resort. 110744d93782SGreg Clayton 11087ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 11097ce2de2cSJonas Devlieghere IOHandlerSP top_reader_sp(m_io_handler_stack.Top()); 111044d93782SGreg Clayton // If no STDIN has been set, then set it appropriately 1111b07823f3SLawrence D'Anna if (!in || !in->IsValid()) { 111244d93782SGreg Clayton if (top_reader_sp) 11137ca15ba7SLawrence D'Anna in = top_reader_sp->GetInputFileSP(); 111444d93782SGreg Clayton else 11157ca15ba7SLawrence D'Anna in = GetInputFileSP(); 111644d93782SGreg Clayton // If there is nothing, use stdin 111744d93782SGreg Clayton if (!in) 1118f913fd6eSLawrence D'Anna in = std::make_shared<NativeFile>(stdin, false); 111944d93782SGreg Clayton } 112044d93782SGreg Clayton // If no STDOUT has been set, then set it appropriately 1121b07823f3SLawrence D'Anna if (!out || !out->GetFile().IsValid()) { 112244d93782SGreg Clayton if (top_reader_sp) 11237ca15ba7SLawrence D'Anna out = top_reader_sp->GetOutputStreamFileSP(); 112444d93782SGreg Clayton else 11257ca15ba7SLawrence D'Anna out = GetOutputStreamSP(); 112644d93782SGreg Clayton // If there is nothing, use stdout 112744d93782SGreg Clayton if (!out) 11282f3df613SZachary Turner out = std::make_shared<StreamFile>(stdout, false); 112944d93782SGreg Clayton } 113044d93782SGreg Clayton // If no STDERR has been set, then set it appropriately 1131b07823f3SLawrence D'Anna if (!err || !err->GetFile().IsValid()) { 113244d93782SGreg Clayton if (top_reader_sp) 11337ca15ba7SLawrence D'Anna err = top_reader_sp->GetErrorStreamFileSP(); 113444d93782SGreg Clayton else 11357ca15ba7SLawrence D'Anna err = GetErrorStreamSP(); 113644d93782SGreg Clayton // If there is nothing, use stderr 113744d93782SGreg Clayton if (!err) 11387ca15ba7SLawrence D'Anna err = std::make_shared<StreamFile>(stderr, false); 113944d93782SGreg Clayton } 114044d93782SGreg Clayton } 114144d93782SGreg Clayton 1142c01783a8SRaphael Isemann void Debugger::PushIOHandler(const IOHandlerSP &reader_sp, 1143c01783a8SRaphael Isemann bool cancel_top_handler) { 114430fdc8d8SChris Lattner if (!reader_sp) 114530fdc8d8SChris Lattner return; 1146b44880caSCaroline Tice 11477ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 11484446487dSPavel Labath 11494446487dSPavel Labath // Get the current top input reader... 11507ce2de2cSJonas Devlieghere IOHandlerSP top_reader_sp(m_io_handler_stack.Top()); 1151b44880caSCaroline Tice 1152b4874f1aSGreg Clayton // Don't push the same IO handler twice... 11534446487dSPavel Labath if (reader_sp == top_reader_sp) 11544446487dSPavel Labath return; 11554446487dSPavel Labath 115644d93782SGreg Clayton // Push our new input reader 11577ce2de2cSJonas Devlieghere m_io_handler_stack.Push(reader_sp); 11584446487dSPavel Labath reader_sp->Activate(); 115944d93782SGreg Clayton 116005097246SAdrian Prantl // Interrupt the top input reader to it will exit its Run() function and let 116105097246SAdrian Prantl // this new input reader take over 1162b9c1b51eSKate Stone if (top_reader_sp) { 116344d93782SGreg Clayton top_reader_sp->Deactivate(); 1164c01783a8SRaphael Isemann if (cancel_top_handler) 11654446487dSPavel Labath top_reader_sp->Cancel(); 116630fdc8d8SChris Lattner } 1167b4874f1aSGreg Clayton } 116830fdc8d8SChris Lattner 1169b9c1b51eSKate Stone bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) { 11704446487dSPavel Labath if (!pop_reader_sp) 11714446487dSPavel Labath return false; 117230fdc8d8SChris Lattner 11737ce2de2cSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(m_io_handler_stack.GetMutex()); 117444d93782SGreg Clayton 117505097246SAdrian Prantl // The reader on the stop of the stack is done, so let the next read on the 117605097246SAdrian Prantl // stack refresh its prompt and if there is one... 11777ce2de2cSJonas Devlieghere if (m_io_handler_stack.IsEmpty()) 11784446487dSPavel Labath return false; 11794446487dSPavel Labath 11807ce2de2cSJonas Devlieghere IOHandlerSP reader_sp(m_io_handler_stack.Top()); 118130fdc8d8SChris Lattner 11824446487dSPavel Labath if (pop_reader_sp != reader_sp) 11834446487dSPavel Labath return false; 11844446487dSPavel Labath 118544d93782SGreg Clayton reader_sp->Deactivate(); 1186b4874f1aSGreg Clayton reader_sp->Cancel(); 11877ce2de2cSJonas Devlieghere m_io_handler_stack.Pop(); 118830fdc8d8SChris Lattner 11897ce2de2cSJonas Devlieghere reader_sp = m_io_handler_stack.Top(); 119030fdc8d8SChris Lattner if (reader_sp) 119144d93782SGreg Clayton reader_sp->Activate(); 119244d93782SGreg Clayton 119344d93782SGreg Clayton return true; 119430fdc8d8SChris Lattner } 11956611103cSGreg Clayton 1196b9c1b51eSKate Stone StreamSP Debugger::GetAsyncOutputStream() { 11972f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, true); 11985b52f0c7SJim Ingham } 11995b52f0c7SJim Ingham 1200b9c1b51eSKate Stone StreamSP Debugger::GetAsyncErrorStream() { 12012f3df613SZachary Turner return std::make_shared<StreamAsynchronousIO>(*this, false); 12025b52f0c7SJim Ingham } 12035b52f0c7SJim Ingham 1204b9c1b51eSKate Stone size_t Debugger::GetNumDebuggers() { 1205b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 12066c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 12076c42e063SGreg Clayton return g_debugger_list_ptr->size(); 1208061858ceSEnrico Granata } 1209c15f55e2SGreg Clayton return 0; 1210c15f55e2SGreg Clayton } 1211061858ceSEnrico Granata 1212b9c1b51eSKate Stone lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) { 1213061858ceSEnrico Granata DebuggerSP debugger_sp; 1214061858ceSEnrico Granata 1215b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 12166c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 12176c42e063SGreg Clayton if (index < g_debugger_list_ptr->size()) 12186c42e063SGreg Clayton debugger_sp = g_debugger_list_ptr->at(index); 1219c15f55e2SGreg Clayton } 1220061858ceSEnrico Granata 1221061858ceSEnrico Granata return debugger_sp; 1222061858ceSEnrico Granata } 1223061858ceSEnrico Granata 1224b9c1b51eSKate Stone DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) { 12254d122c40SGreg Clayton DebuggerSP debugger_sp; 1226ebc1bb27SCaroline Tice 1227b9c1b51eSKate Stone if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 12286c42e063SGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 12296c42e063SGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 1230b9c1b51eSKate Stone for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { 1231b9c1b51eSKate Stone if ((*pos)->GetID() == id) { 1232ebc1bb27SCaroline Tice debugger_sp = *pos; 1233ebc1bb27SCaroline Tice break; 1234ebc1bb27SCaroline Tice } 1235ebc1bb27SCaroline Tice } 1236c15f55e2SGreg Clayton } 1237ebc1bb27SCaroline Tice return debugger_sp; 1238ebc1bb27SCaroline Tice } 12393df9a8dfSCaroline Tice 1240b9c1b51eSKate Stone bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, 1241aff1b357SJason Molenda const SymbolContext *sc, 1242aff1b357SJason Molenda const SymbolContext *prev_sc, 1243aff1b357SJason Molenda const ExecutionContext *exe_ctx, 1244b9c1b51eSKate Stone const Address *addr, Stream &s) { 1245554f68d3SGreg Clayton FormatEntity::Entry format_entry; 1246554f68d3SGreg Clayton 1247b9c1b51eSKate Stone if (format == nullptr) { 1248df370550SEugene Zelenko if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) 1249aff1b357SJason Molenda format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); 1250b9c1b51eSKate Stone if (format == nullptr) { 1251554f68d3SGreg Clayton FormatEntity::Parse("${addr}: ", format_entry); 1252554f68d3SGreg Clayton format = &format_entry; 1253554f68d3SGreg Clayton } 1254aff1b357SJason Molenda } 1255aff1b357SJason Molenda bool function_changed = false; 1256aff1b357SJason Molenda bool initial_function = false; 1257b9c1b51eSKate Stone if (prev_sc && (prev_sc->function || prev_sc->symbol)) { 1258b9c1b51eSKate Stone if (sc && (sc->function || sc->symbol)) { 1259b9c1b51eSKate Stone if (prev_sc->symbol && sc->symbol) { 1260b9c1b51eSKate Stone if (!sc->symbol->Compare(prev_sc->symbol->GetName(), 1261b9c1b51eSKate Stone prev_sc->symbol->GetType())) { 1262aff1b357SJason Molenda function_changed = true; 1263aff1b357SJason Molenda } 1264b9c1b51eSKate Stone } else if (prev_sc->function && sc->function) { 1265b9c1b51eSKate Stone if (prev_sc->function->GetMangled() != sc->function->GetMangled()) { 1266aff1b357SJason Molenda function_changed = true; 1267aff1b357SJason Molenda } 1268aff1b357SJason Molenda } 1269aff1b357SJason Molenda } 1270aff1b357SJason Molenda } 127105097246SAdrian Prantl // The first context on a list of instructions will have a prev_sc that has 127205097246SAdrian Prantl // no Function or Symbol -- if SymbolContext had an IsValid() method, it 1273aff1b357SJason Molenda // would return false. But we do get a prev_sc pointer. 1274b9c1b51eSKate Stone if ((sc && (sc->function || sc->symbol)) && prev_sc && 1275b9c1b51eSKate Stone (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) { 1276aff1b357SJason Molenda initial_function = true; 1277aff1b357SJason Molenda } 1278b9c1b51eSKate Stone return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, 1279b9c1b51eSKate Stone function_changed, initial_function); 1280aff1b357SJason Molenda } 1281aff1b357SJason Molenda 1282b9c1b51eSKate Stone void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, 1283b9c1b51eSKate Stone void *baton) { 12844f02b22dSJim Ingham // For simplicity's sake, I am not going to deal with how to close down any 12854f02b22dSJim Ingham // open logging streams, I just redirect everything from here on out to the 12864f02b22dSJim Ingham // callback. 12872f3df613SZachary Turner m_log_callback_stream_sp = 12882f3df613SZachary Turner std::make_shared<StreamCallback>(log_callback, baton); 1289228063cdSJim Ingham } 1290228063cdSJim Ingham 1291e122877fSGreg Clayton static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, 1292e122877fSGreg Clayton const std::string &message, 1293e122877fSGreg Clayton uint64_t completed, uint64_t total, 1294e122877fSGreg Clayton bool is_debugger_specific) { 1295e122877fSGreg Clayton // Only deliver progress events if we have any progress listeners. 1296e122877fSGreg Clayton const uint32_t event_type = Debugger::eBroadcastBitProgress; 1297e122877fSGreg Clayton if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type)) 1298e122877fSGreg Clayton return; 12995e65e79bSJonas Devlieghere EventSP event_sp(new Event( 13005e65e79bSJonas Devlieghere event_type, new ProgressEventData(progress_id, message, completed, total, 13015e65e79bSJonas Devlieghere is_debugger_specific))); 1302e122877fSGreg Clayton debugger.GetBroadcaster().BroadcastEvent(event_sp); 1303e122877fSGreg Clayton } 1304e122877fSGreg Clayton 1305e122877fSGreg Clayton void Debugger::ReportProgress(uint64_t progress_id, const std::string &message, 1306e122877fSGreg Clayton uint64_t completed, uint64_t total, 1307e122877fSGreg Clayton llvm::Optional<lldb::user_id_t> debugger_id) { 1308e122877fSGreg Clayton // Check if this progress is for a specific debugger. 1309e122877fSGreg Clayton if (debugger_id.hasValue()) { 1310e122877fSGreg Clayton // It is debugger specific, grab it and deliver the event if the debugger 1311e122877fSGreg Clayton // still exists. 1312e122877fSGreg Clayton DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id); 1313e122877fSGreg Clayton if (debugger_sp) 1314e122877fSGreg Clayton PrivateReportProgress(*debugger_sp, progress_id, message, completed, 1315e122877fSGreg Clayton total, /*is_debugger_specific*/ true); 1316e122877fSGreg Clayton return; 1317e122877fSGreg Clayton } 1318e122877fSGreg Clayton // The progress event is not debugger specific, iterate over all debuggers 1319e122877fSGreg Clayton // and deliver a progress event to each one. 1320e122877fSGreg Clayton if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 1321e122877fSGreg Clayton std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 1322e122877fSGreg Clayton DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); 1323e122877fSGreg Clayton for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) 1324e122877fSGreg Clayton PrivateReportProgress(*(*pos), progress_id, message, completed, total, 1325e122877fSGreg Clayton /*is_debugger_specific*/ false); 1326e122877fSGreg Clayton } 1327e122877fSGreg Clayton } 1328e122877fSGreg Clayton 1329*2fc38b2bSJonas Devlieghere static void PrivateReportDiagnostic(Debugger &debugger, 1330*2fc38b2bSJonas Devlieghere DiagnosticEventData::Type type, 1331*2fc38b2bSJonas Devlieghere std::string message, 1332*2fc38b2bSJonas Devlieghere bool debugger_specific) { 1333*2fc38b2bSJonas Devlieghere uint32_t event_type = 0; 1334*2fc38b2bSJonas Devlieghere switch (type) { 1335*2fc38b2bSJonas Devlieghere case DiagnosticEventData::Type::Warning: 1336*2fc38b2bSJonas Devlieghere event_type = Debugger::eBroadcastBitWarning; 1337*2fc38b2bSJonas Devlieghere break; 1338*2fc38b2bSJonas Devlieghere case DiagnosticEventData::Type::Error: 1339*2fc38b2bSJonas Devlieghere event_type = Debugger::eBroadcastBitError; 1340*2fc38b2bSJonas Devlieghere break; 1341*2fc38b2bSJonas Devlieghere } 1342*2fc38b2bSJonas Devlieghere 1343*2fc38b2bSJonas Devlieghere Broadcaster &broadcaster = debugger.GetBroadcaster(); 1344*2fc38b2bSJonas Devlieghere if (!broadcaster.EventTypeHasListeners(event_type)) { 1345*2fc38b2bSJonas Devlieghere // Diagnostics are too important to drop. If nobody is listening, print the 1346*2fc38b2bSJonas Devlieghere // diagnostic directly to the debugger's error stream. 1347*2fc38b2bSJonas Devlieghere DiagnosticEventData event_data(type, std::move(message), debugger_specific); 1348*2fc38b2bSJonas Devlieghere StreamSP stream = debugger.GetAsyncErrorStream(); 1349*2fc38b2bSJonas Devlieghere event_data.Dump(stream.get()); 1350*2fc38b2bSJonas Devlieghere return; 1351*2fc38b2bSJonas Devlieghere } 1352*2fc38b2bSJonas Devlieghere EventSP event_sp = std::make_shared<Event>( 1353*2fc38b2bSJonas Devlieghere event_type, 1354*2fc38b2bSJonas Devlieghere new DiagnosticEventData(type, std::move(message), debugger_specific)); 1355*2fc38b2bSJonas Devlieghere broadcaster.BroadcastEvent(event_sp); 1356*2fc38b2bSJonas Devlieghere } 1357*2fc38b2bSJonas Devlieghere 1358*2fc38b2bSJonas Devlieghere void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type, 1359*2fc38b2bSJonas Devlieghere std::string message, 1360*2fc38b2bSJonas Devlieghere llvm::Optional<lldb::user_id_t> debugger_id, 1361*2fc38b2bSJonas Devlieghere std::once_flag *once) { 1362*2fc38b2bSJonas Devlieghere auto ReportDiagnosticLambda = [&]() { 1363*2fc38b2bSJonas Devlieghere // Check if this progress is for a specific debugger. 1364*2fc38b2bSJonas Devlieghere if (debugger_id) { 1365*2fc38b2bSJonas Devlieghere // It is debugger specific, grab it and deliver the event if the debugger 1366*2fc38b2bSJonas Devlieghere // still exists. 1367*2fc38b2bSJonas Devlieghere DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id); 1368*2fc38b2bSJonas Devlieghere if (debugger_sp) 1369*2fc38b2bSJonas Devlieghere PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true); 1370*2fc38b2bSJonas Devlieghere return; 1371*2fc38b2bSJonas Devlieghere } 1372*2fc38b2bSJonas Devlieghere // The progress event is not debugger specific, iterate over all debuggers 1373*2fc38b2bSJonas Devlieghere // and deliver a progress event to each one. 1374*2fc38b2bSJonas Devlieghere if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { 1375*2fc38b2bSJonas Devlieghere std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); 1376*2fc38b2bSJonas Devlieghere for (const auto &debugger : *g_debugger_list_ptr) 1377*2fc38b2bSJonas Devlieghere PrivateReportDiagnostic(*debugger, type, message, false); 1378*2fc38b2bSJonas Devlieghere } 1379*2fc38b2bSJonas Devlieghere }; 1380*2fc38b2bSJonas Devlieghere 1381*2fc38b2bSJonas Devlieghere if (once) 1382*2fc38b2bSJonas Devlieghere std::call_once(*once, ReportDiagnosticLambda); 1383*2fc38b2bSJonas Devlieghere else 1384*2fc38b2bSJonas Devlieghere ReportDiagnosticLambda(); 1385*2fc38b2bSJonas Devlieghere } 1386*2fc38b2bSJonas Devlieghere 1387*2fc38b2bSJonas Devlieghere void Debugger::ReportWarning(std::string message, 1388*2fc38b2bSJonas Devlieghere llvm::Optional<lldb::user_id_t> debugger_id, 1389*2fc38b2bSJonas Devlieghere std::once_flag *once) { 1390*2fc38b2bSJonas Devlieghere ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message), 1391*2fc38b2bSJonas Devlieghere debugger_id, once); 1392*2fc38b2bSJonas Devlieghere } 1393*2fc38b2bSJonas Devlieghere 1394*2fc38b2bSJonas Devlieghere void Debugger::ReportError(std::string message, 1395*2fc38b2bSJonas Devlieghere llvm::Optional<lldb::user_id_t> debugger_id, 1396*2fc38b2bSJonas Devlieghere std::once_flag *once) { 1397*2fc38b2bSJonas Devlieghere 1398*2fc38b2bSJonas Devlieghere ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message), 1399*2fc38b2bSJonas Devlieghere debugger_id, once); 1400*2fc38b2bSJonas Devlieghere } 1401*2fc38b2bSJonas Devlieghere 14025e336903SPavel Labath bool Debugger::EnableLog(llvm::StringRef channel, 14035e336903SPavel Labath llvm::ArrayRef<const char *> categories, 14045e336903SPavel Labath llvm::StringRef log_file, uint32_t log_options, 1405775588c0SPavel Labath llvm::raw_ostream &error_stream) { 14065fae71c5SPavel Labath const bool should_close = true; 14075fae71c5SPavel Labath const bool unbuffered = true; 14085fae71c5SPavel Labath 14095fae71c5SPavel Labath std::shared_ptr<llvm::raw_ostream> log_stream_sp; 1410b9c1b51eSKate Stone if (m_log_callback_stream_sp) { 1411228063cdSJim Ingham log_stream_sp = m_log_callback_stream_sp; 1412228063cdSJim Ingham // For now when using the callback mode you always get thread & timestamp. 1413b9c1b51eSKate Stone log_options |= 1414b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; 14155e336903SPavel Labath } else if (log_file.empty()) { 14165fae71c5SPavel Labath log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( 14177ca15ba7SLawrence D'Anna GetOutputFile().GetDescriptor(), !should_close, unbuffered); 1418b9c1b51eSKate Stone } else { 14195fae71c5SPavel Labath auto pos = m_log_streams.find(log_file); 1420c1b2ccfdSGreg Clayton if (pos != m_log_streams.end()) 1421c1b2ccfdSGreg Clayton log_stream_sp = pos->second.lock(); 1422b9c1b51eSKate Stone if (!log_stream_sp) { 14236b2e6765SJonas Devlieghere File::OpenOptions flags = 142414735cabSMichał Górny File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate; 14255fae71c5SPavel Labath if (log_options & LLDB_LOG_OPTION_APPEND) 14266b2e6765SJonas Devlieghere flags |= File::eOpenOptionAppend; 14276b2e6765SJonas Devlieghere else 14286b2e6765SJonas Devlieghere flags |= File::eOpenOptionTruncate; 1429867c347cSRaphael Isemann llvm::Expected<FileUP> file = FileSystem::Instance().Open( 14306b2e6765SJonas Devlieghere FileSpec(log_file), flags, lldb::eFilePermissionsFileDefault, false); 14316b2e6765SJonas Devlieghere if (!file) { 1432867c347cSRaphael Isemann error_stream << "Unable to open log file '" << log_file 1433867c347cSRaphael Isemann << "': " << llvm::toString(file.takeError()) << "\n"; 14345fae71c5SPavel Labath return false; 14355fae71c5SPavel Labath } 14366b2e6765SJonas Devlieghere 14376b2e6765SJonas Devlieghere log_stream_sp = std::make_shared<llvm::raw_fd_ostream>( 14386b2e6765SJonas Devlieghere (*file)->GetDescriptor(), should_close, unbuffered); 1439228063cdSJim Ingham m_log_streams[log_file] = log_stream_sp; 1440228063cdSJim Ingham } 1441228063cdSJim Ingham } 1442df370550SEugene Zelenko assert(log_stream_sp); 1443228063cdSJim Ingham 1444228063cdSJim Ingham if (log_options == 0) 1445b9c1b51eSKate Stone log_options = 1446b9c1b51eSKate Stone LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; 1447228063cdSJim Ingham 1448b9c1b51eSKate Stone return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories, 1449b9c1b51eSKate Stone error_stream); 1450228063cdSJim Ingham } 1451228063cdSJim Ingham 1452bbf70c04SJonas Devlieghere ScriptInterpreter * 1453bbf70c04SJonas Devlieghere Debugger::GetScriptInterpreter(bool can_create, 1454bbf70c04SJonas Devlieghere llvm::Optional<lldb::ScriptLanguage> language) { 14552b29b432SJonas Devlieghere std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex); 1456bbf70c04SJonas Devlieghere lldb::ScriptLanguage script_language = 1457bbf70c04SJonas Devlieghere language ? *language : GetScriptLanguage(); 14582b29b432SJonas Devlieghere 1459bbf70c04SJonas Devlieghere if (!m_script_interpreters[script_language]) { 14602b29b432SJonas Devlieghere if (!can_create) 14612b29b432SJonas Devlieghere return nullptr; 1462bbf70c04SJonas Devlieghere m_script_interpreters[script_language] = 1463bbf70c04SJonas Devlieghere PluginManager::GetScriptInterpreterForLanguage(script_language, *this); 14642b29b432SJonas Devlieghere } 14652b29b432SJonas Devlieghere 1466bbf70c04SJonas Devlieghere return m_script_interpreters[script_language].get(); 14672b29b432SJonas Devlieghere } 14682b29b432SJonas Devlieghere 1469b9c1b51eSKate Stone SourceManager &Debugger::GetSourceManager() { 1470d5b44036SJonas Devlieghere if (!m_source_manager_up) 1471a8f3ae7cSJonas Devlieghere m_source_manager_up = std::make_unique<SourceManager>(shared_from_this()); 1472d5b44036SJonas Devlieghere return *m_source_manager_up; 14739585fbfcSGreg Clayton } 14749585fbfcSGreg Clayton 147544d93782SGreg Clayton // This function handles events that were broadcast by the process. 1476b9c1b51eSKate Stone void Debugger::HandleBreakpointEvent(const EventSP &event_sp) { 147744d93782SGreg Clayton using namespace lldb; 1478b9c1b51eSKate Stone const uint32_t event_type = 1479b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( 1480b9c1b51eSKate Stone event_sp); 148144d93782SGreg Clayton 148244d93782SGreg Clayton // if (event_type & eBreakpointEventTypeAdded 148344d93782SGreg Clayton // || event_type & eBreakpointEventTypeRemoved 148444d93782SGreg Clayton // || event_type & eBreakpointEventTypeEnabled 148544d93782SGreg Clayton // || event_type & eBreakpointEventTypeDisabled 148644d93782SGreg Clayton // || event_type & eBreakpointEventTypeCommandChanged 148744d93782SGreg Clayton // || event_type & eBreakpointEventTypeConditionChanged 148844d93782SGreg Clayton // || event_type & eBreakpointEventTypeIgnoreChanged 148944d93782SGreg Clayton // || event_type & eBreakpointEventTypeLocationsResolved) 149044d93782SGreg Clayton // { 1491b9c1b51eSKate Stone // // Don't do anything about these events, since the breakpoint 1492b9c1b51eSKate Stone // commands already echo these actions. 149344d93782SGreg Clayton // } 149444d93782SGreg Clayton // 1495b9c1b51eSKate Stone if (event_type & eBreakpointEventTypeLocationsAdded) { 1496b9c1b51eSKate Stone uint32_t num_new_locations = 1497b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( 1498b9c1b51eSKate Stone event_sp); 1499b9c1b51eSKate Stone if (num_new_locations > 0) { 1500b9c1b51eSKate Stone BreakpointSP breakpoint = 1501b9c1b51eSKate Stone Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); 15024446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1503b9c1b51eSKate Stone if (output_sp) { 150444d93782SGreg Clayton output_sp->Printf("%d location%s added to breakpoint %d\n", 1505b9c1b51eSKate Stone num_new_locations, num_new_locations == 1 ? "" : "s", 150644d93782SGreg Clayton breakpoint->GetID()); 15074446487dSPavel Labath output_sp->Flush(); 150844d93782SGreg Clayton } 150944d93782SGreg Clayton } 151044d93782SGreg Clayton } 151144d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsRemoved) 151244d93782SGreg Clayton // { 1513b9c1b51eSKate Stone // // These locations just get disabled, not sure it is worth spamming 1514b9c1b51eSKate Stone // folks about this on the command line. 151544d93782SGreg Clayton // } 151644d93782SGreg Clayton // else if (event_type & eBreakpointEventTypeLocationsResolved) 151744d93782SGreg Clayton // { 1518b9c1b51eSKate Stone // // This might be an interesting thing to note, but I'm going to 1519b9c1b51eSKate Stone // leave it quiet for now, it just looked noisy. 152044d93782SGreg Clayton // } 152144d93782SGreg Clayton } 152244d93782SGreg Clayton 1523a9d58436SPavel Labath void Debugger::FlushProcessOutput(Process &process, bool flush_stdout, 1524a9d58436SPavel Labath bool flush_stderr) { 1525a9d58436SPavel Labath const auto &flush = [&](Stream &stream, 1526a9d58436SPavel Labath size_t (Process::*get)(char *, size_t, Status &)) { 152797206d57SZachary Turner Status error; 152844d93782SGreg Clayton size_t len; 1529a9d58436SPavel Labath char buffer[1024]; 1530a9d58436SPavel Labath while ((len = (process.*get)(buffer, sizeof(buffer), error)) > 0) 1531a9d58436SPavel Labath stream.Write(buffer, len); 1532a9d58436SPavel Labath stream.Flush(); 1533a9d58436SPavel Labath }; 153444d93782SGreg Clayton 1535a9d58436SPavel Labath std::lock_guard<std::mutex> guard(m_output_flush_mutex); 1536a9d58436SPavel Labath if (flush_stdout) 1537a9d58436SPavel Labath flush(*GetAsyncOutputStream(), &Process::GetSTDOUT); 1538a9d58436SPavel Labath if (flush_stderr) 1539a9d58436SPavel Labath flush(*GetAsyncErrorStream(), &Process::GetSTDERR); 154044d93782SGreg Clayton } 154144d93782SGreg Clayton 154244d93782SGreg Clayton // This function handles events that were broadcast by the process. 1543b9c1b51eSKate Stone void Debugger::HandleProcessEvent(const EventSP &event_sp) { 154444d93782SGreg Clayton using namespace lldb; 154544d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 1546b9c1b51eSKate Stone ProcessSP process_sp = 1547b9c1b51eSKate Stone (event_type == Process::eBroadcastBitStructuredData) 154875930019STodd Fiala ? EventDataStructuredData::GetProcessFromEvent(event_sp.get()) 154975930019STodd Fiala : Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); 155044d93782SGreg Clayton 15514446487dSPavel Labath StreamSP output_stream_sp = GetAsyncOutputStream(); 15524446487dSPavel Labath StreamSP error_stream_sp = GetAsyncErrorStream(); 155344d93782SGreg Clayton const bool gui_enabled = IsForwardingEvents(); 155444d93782SGreg Clayton 1555b9c1b51eSKate Stone if (!gui_enabled) { 1556b4874f1aSGreg Clayton bool pop_process_io_handler = false; 155744d93782SGreg Clayton assert(process_sp); 155844d93782SGreg Clayton 15594446487dSPavel Labath bool state_is_stopped = false; 1560b9c1b51eSKate Stone const bool got_state_changed = 1561b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStateChanged) != 0; 15624446487dSPavel Labath const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0; 15634446487dSPavel Labath const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0; 1564b9c1b51eSKate Stone const bool got_structured_data = 1565b9c1b51eSKate Stone (event_type & Process::eBroadcastBitStructuredData) != 0; 156675930019STodd Fiala 1567b9c1b51eSKate Stone if (got_state_changed) { 1568b9c1b51eSKate Stone StateType event_state = 1569b9c1b51eSKate Stone Process::ProcessEventData::GetStateFromEvent(event_sp.get()); 15704446487dSPavel Labath state_is_stopped = StateIsStoppedState(event_state, false); 157144d93782SGreg Clayton } 1572b4874f1aSGreg Clayton 15734446487dSPavel Labath // Display running state changes first before any STDIO 1574b9c1b51eSKate Stone if (got_state_changed && !state_is_stopped) { 1575b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1576b9c1b51eSKate Stone pop_process_io_handler); 157744d93782SGreg Clayton } 1578b4874f1aSGreg Clayton 1579a9d58436SPavel Labath // Now display STDOUT and STDERR 1580a9d58436SPavel Labath FlushProcessOutput(*process_sp, got_stdout || got_state_changed, 1581a9d58436SPavel Labath got_stderr || got_state_changed); 1582b4874f1aSGreg Clayton 158375930019STodd Fiala // Give structured data events an opportunity to display. 1584b9c1b51eSKate Stone if (got_structured_data) { 158575930019STodd Fiala StructuredDataPluginSP plugin_sp = 158675930019STodd Fiala EventDataStructuredData::GetPluginFromEvent(event_sp.get()); 1587b9c1b51eSKate Stone if (plugin_sp) { 158875930019STodd Fiala auto structured_data_sp = 158975930019STodd Fiala EventDataStructuredData::GetObjectFromEvent(event_sp.get()); 1590b9c1b51eSKate Stone if (output_stream_sp) { 159175930019STodd Fiala StreamString content_stream; 159297206d57SZachary Turner Status error = 1593b9c1b51eSKate Stone plugin_sp->GetDescription(structured_data_sp, content_stream); 1594b9c1b51eSKate Stone if (error.Success()) { 1595b9c1b51eSKate Stone if (!content_stream.GetString().empty()) { 159675930019STodd Fiala // Add newline. 159775930019STodd Fiala content_stream.PutChar('\n'); 159875930019STodd Fiala content_stream.Flush(); 159975930019STodd Fiala 160075930019STodd Fiala // Print it. 1601771ef6d4SMalcolm Parsons output_stream_sp->PutCString(content_stream.GetString()); 160275930019STodd Fiala } 1603b9c1b51eSKate Stone } else { 1604a3939e15SPavel Labath error_stream_sp->Format("Failed to print structured " 1605a3939e15SPavel Labath "data with plugin {0}: {1}", 1606a3939e15SPavel Labath plugin_sp->GetPluginName(), error); 160775930019STodd Fiala } 160875930019STodd Fiala } 160975930019STodd Fiala } 161075930019STodd Fiala } 161175930019STodd Fiala 16124446487dSPavel Labath // Now display any stopped state changes after any STDIO 1613b9c1b51eSKate Stone if (got_state_changed && state_is_stopped) { 1614b9c1b51eSKate Stone Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), 1615b9c1b51eSKate Stone pop_process_io_handler); 161644d93782SGreg Clayton } 161744d93782SGreg Clayton 16184446487dSPavel Labath output_stream_sp->Flush(); 16194446487dSPavel Labath error_stream_sp->Flush(); 162044d93782SGreg Clayton 1621b4874f1aSGreg Clayton if (pop_process_io_handler) 1622b4874f1aSGreg Clayton process_sp->PopProcessIOHandler(); 1623b4874f1aSGreg Clayton } 1624b4874f1aSGreg Clayton } 1625b4874f1aSGreg Clayton 1626b9c1b51eSKate Stone void Debugger::HandleThreadEvent(const EventSP &event_sp) { 162705097246SAdrian Prantl // At present the only thread event we handle is the Frame Changed event, and 162805097246SAdrian Prantl // all we do for that is just reprint the thread status for that thread. 162944d93782SGreg Clayton using namespace lldb; 163044d93782SGreg Clayton const uint32_t event_type = event_sp->GetType(); 16316a9767c7SJim Ingham const bool stop_format = true; 163244d93782SGreg Clayton if (event_type == Thread::eBroadcastBitStackChanged || 1633b9c1b51eSKate Stone event_type == Thread::eBroadcastBitThreadSelected) { 1634b9c1b51eSKate Stone ThreadSP thread_sp( 1635b9c1b51eSKate Stone Thread::ThreadEventData::GetThreadFromEvent(event_sp.get())); 1636b9c1b51eSKate Stone if (thread_sp) { 16376a9767c7SJim Ingham thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format); 163844d93782SGreg Clayton } 163944d93782SGreg Clayton } 164044d93782SGreg Clayton } 164144d93782SGreg Clayton 1642b9c1b51eSKate Stone bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; } 164344d93782SGreg Clayton 1644b9c1b51eSKate Stone void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) { 164544d93782SGreg Clayton m_forward_listener_sp = listener_sp; 164644d93782SGreg Clayton } 164744d93782SGreg Clayton 1648b9c1b51eSKate Stone void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) { 164944d93782SGreg Clayton m_forward_listener_sp.reset(); 165044d93782SGreg Clayton } 165144d93782SGreg Clayton 1652d0810779SPavel Labath lldb::thread_result_t Debugger::DefaultEventHandler() { 1653583bbb1dSJim Ingham ListenerSP listener_sp(GetListener()); 165444d93782SGreg Clayton ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); 165544d93782SGreg Clayton ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); 165644d93782SGreg Clayton ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); 165744d93782SGreg Clayton BroadcastEventSpec target_event_spec(broadcaster_class_target, 165844d93782SGreg Clayton Target::eBroadcastBitBreakpointChanged); 165944d93782SGreg Clayton 1660b9c1b51eSKate Stone BroadcastEventSpec process_event_spec( 1661b9c1b51eSKate Stone broadcaster_class_process, 1662b9c1b51eSKate Stone Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT | 1663b9c1b51eSKate Stone Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData); 166444d93782SGreg Clayton 166544d93782SGreg Clayton BroadcastEventSpec thread_event_spec(broadcaster_class_thread, 166644d93782SGreg Clayton Thread::eBroadcastBitStackChanged | 166744d93782SGreg Clayton Thread::eBroadcastBitThreadSelected); 166844d93782SGreg Clayton 1669b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1670b9c1b51eSKate Stone target_event_spec); 1671b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1672b9c1b51eSKate Stone process_event_spec); 1673b9c1b51eSKate Stone listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, 1674b9c1b51eSKate Stone thread_event_spec); 1675b9c1b51eSKate Stone listener_sp->StartListeningForEvents( 1676d5b44036SJonas Devlieghere m_command_interpreter_up.get(), 167744d93782SGreg Clayton CommandInterpreter::eBroadcastBitQuitCommandReceived | 167844d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousOutputData | 167944d93782SGreg Clayton CommandInterpreter::eBroadcastBitAsynchronousErrorData); 168044d93782SGreg Clayton 1681*2fc38b2bSJonas Devlieghere listener_sp->StartListeningForEvents( 1682*2fc38b2bSJonas Devlieghere &m_broadcaster, 1683*2fc38b2bSJonas Devlieghere eBroadcastBitProgress | eBroadcastBitWarning | eBroadcastBitError); 16845a27b998SJonas Devlieghere 168505097246SAdrian Prantl // Let the thread that spawned us know that we have started up and that we 168605097246SAdrian Prantl // are now listening to all required events so no events get missed 1687afa91e33SGreg Clayton m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); 1688afa91e33SGreg Clayton 168944d93782SGreg Clayton bool done = false; 1690b9c1b51eSKate Stone while (!done) { 169144d93782SGreg Clayton EventSP event_sp; 1692d35031e1SPavel Labath if (listener_sp->GetEvent(event_sp, llvm::None)) { 1693b9c1b51eSKate Stone if (event_sp) { 169444d93782SGreg Clayton Broadcaster *broadcaster = event_sp->GetBroadcaster(); 1695b9c1b51eSKate Stone if (broadcaster) { 169644d93782SGreg Clayton uint32_t event_type = event_sp->GetType(); 169744d93782SGreg Clayton ConstString broadcaster_class(broadcaster->GetBroadcasterClass()); 1698b9c1b51eSKate Stone if (broadcaster_class == broadcaster_class_process) { 169944d93782SGreg Clayton HandleProcessEvent(event_sp); 1700b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_target) { 1701b9c1b51eSKate Stone if (Breakpoint::BreakpointEventData::GetEventDataFromEvent( 1702b9c1b51eSKate Stone event_sp.get())) { 170344d93782SGreg Clayton HandleBreakpointEvent(event_sp); 170444d93782SGreg Clayton } 1705b9c1b51eSKate Stone } else if (broadcaster_class == broadcaster_class_thread) { 170644d93782SGreg Clayton HandleThreadEvent(event_sp); 1707d5b44036SJonas Devlieghere } else if (broadcaster == m_command_interpreter_up.get()) { 1708b9c1b51eSKate Stone if (event_type & 1709b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived) { 171044d93782SGreg Clayton done = true; 1711b9c1b51eSKate Stone } else if (event_type & 1712b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitAsynchronousErrorData) { 171365fdb342SRaphael Isemann const char *data = static_cast<const char *>( 1714b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1715b9c1b51eSKate Stone if (data && data[0]) { 17164446487dSPavel Labath StreamSP error_sp(GetAsyncErrorStream()); 1717b9c1b51eSKate Stone if (error_sp) { 171844d93782SGreg Clayton error_sp->PutCString(data); 171944d93782SGreg Clayton error_sp->Flush(); 172044d93782SGreg Clayton } 172144d93782SGreg Clayton } 1722b9c1b51eSKate Stone } else if (event_type & CommandInterpreter:: 1723b9c1b51eSKate Stone eBroadcastBitAsynchronousOutputData) { 172465fdb342SRaphael Isemann const char *data = static_cast<const char *>( 1725b9c1b51eSKate Stone EventDataBytes::GetBytesFromEvent(event_sp.get())); 1726b9c1b51eSKate Stone if (data && data[0]) { 17274446487dSPavel Labath StreamSP output_sp(GetAsyncOutputStream()); 1728b9c1b51eSKate Stone if (output_sp) { 172944d93782SGreg Clayton output_sp->PutCString(data); 173044d93782SGreg Clayton output_sp->Flush(); 173144d93782SGreg Clayton } 173244d93782SGreg Clayton } 173344d93782SGreg Clayton } 17345a27b998SJonas Devlieghere } else if (broadcaster == &m_broadcaster) { 17355a27b998SJonas Devlieghere if (event_type & Debugger::eBroadcastBitProgress) 17365a27b998SJonas Devlieghere HandleProgressEvent(event_sp); 1737*2fc38b2bSJonas Devlieghere else if (event_type & Debugger::eBroadcastBitWarning) 1738*2fc38b2bSJonas Devlieghere HandleDiagnosticEvent(event_sp); 1739*2fc38b2bSJonas Devlieghere else if (event_type & Debugger::eBroadcastBitError) 1740*2fc38b2bSJonas Devlieghere HandleDiagnosticEvent(event_sp); 174144d93782SGreg Clayton } 174244d93782SGreg Clayton } 174344d93782SGreg Clayton 174444d93782SGreg Clayton if (m_forward_listener_sp) 174544d93782SGreg Clayton m_forward_listener_sp->AddEvent(event_sp); 174644d93782SGreg Clayton } 174744d93782SGreg Clayton } 174844d93782SGreg Clayton } 174985200645SKonrad Kleine return {}; 175044d93782SGreg Clayton } 175144d93782SGreg Clayton 1752b9c1b51eSKate Stone bool Debugger::StartEventHandlerThread() { 1753b9c1b51eSKate Stone if (!m_event_handler_thread.IsJoinable()) { 175405097246SAdrian Prantl // We must synchronize with the DefaultEventHandler() thread to ensure it 175505097246SAdrian Prantl // is up and running and listening to events before we return from this 175605097246SAdrian Prantl // function. We do this by listening to events for the 1757afa91e33SGreg Clayton // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster 17581a728f66STatyana Krasnukha ConstString full_name("lldb.debugger.event-handler"); 17591a728f66STatyana Krasnukha ListenerSP listener_sp(Listener::MakeListener(full_name.AsCString())); 1760b9c1b51eSKate Stone listener_sp->StartListeningForEvents(&m_sync_broadcaster, 1761b9c1b51eSKate Stone eBroadcastBitEventThreadIsListening); 1762afa91e33SGreg Clayton 1763642bc15dSRaphael Isemann llvm::StringRef thread_name = 1764e063ecccSJonas Devlieghere full_name.GetLength() < llvm::get_max_thread_name_length() 1765642bc15dSRaphael Isemann ? full_name.GetStringRef() 1766e063ecccSJonas Devlieghere : "dbg.evt-handler"; 17671a728f66STatyana Krasnukha 17687c2896a2SZachary Turner // Use larger 8MB stack for this thread 1769f39c2e18SJonas Devlieghere llvm::Expected<HostThread> event_handler_thread = 1770d0810779SPavel Labath ThreadLauncher::LaunchThread( 1771d0810779SPavel Labath thread_name, [this] { return DefaultEventHandler(); }, 1772f39c2e18SJonas Devlieghere g_debugger_event_thread_stack_bytes); 1773f39c2e18SJonas Devlieghere 1774f39c2e18SJonas Devlieghere if (event_handler_thread) { 1775f39c2e18SJonas Devlieghere m_event_handler_thread = *event_handler_thread; 1776f39c2e18SJonas Devlieghere } else { 1777a007a6d8SPavel Labath LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", 1778f39c2e18SJonas Devlieghere llvm::toString(event_handler_thread.takeError())); 1779f39c2e18SJonas Devlieghere } 1780afa91e33SGreg Clayton 178105097246SAdrian Prantl // Make sure DefaultEventHandler() is running and listening to events 178205097246SAdrian Prantl // before we return from this function. We are only listening for events of 178305097246SAdrian Prantl // type eBroadcastBitEventThreadIsListening so we don't need to check the 178405097246SAdrian Prantl // event, we just need to wait an infinite amount of time for it (nullptr 178505097246SAdrian Prantl // timeout as the first parameter) 1786afa91e33SGreg Clayton lldb::EventSP event_sp; 1787d35031e1SPavel Labath listener_sp->GetEvent(event_sp, llvm::None); 1788807b6b32SGreg Clayton } 1789acee96aeSZachary Turner return m_event_handler_thread.IsJoinable(); 179044d93782SGreg Clayton } 179144d93782SGreg Clayton 1792b9c1b51eSKate Stone void Debugger::StopEventHandlerThread() { 1793b9c1b51eSKate Stone if (m_event_handler_thread.IsJoinable()) { 1794b9c1b51eSKate Stone GetCommandInterpreter().BroadcastEvent( 1795b9c1b51eSKate Stone CommandInterpreter::eBroadcastBitQuitCommandReceived); 179639de3110SZachary Turner m_event_handler_thread.Join(nullptr); 179744d93782SGreg Clayton } 179844d93782SGreg Clayton } 179944d93782SGreg Clayton 1800d0810779SPavel Labath lldb::thread_result_t Debugger::IOHandlerThread() { 1801d0810779SPavel Labath RunIOHandlers(); 1802d0810779SPavel Labath StopEventHandlerThread(); 180385200645SKonrad Kleine return {}; 180444d93782SGreg Clayton } 180544d93782SGreg Clayton 18065a27b998SJonas Devlieghere void Debugger::HandleProgressEvent(const lldb::EventSP &event_sp) { 18075e65e79bSJonas Devlieghere auto *data = ProgressEventData::GetEventDataFromEvent(event_sp.get()); 18085a27b998SJonas Devlieghere if (!data) 18095a27b998SJonas Devlieghere return; 18105a27b998SJonas Devlieghere 18115a27b998SJonas Devlieghere // Do some bookkeeping for the current event, regardless of whether we're 18125a27b998SJonas Devlieghere // going to show the progress. 18135a27b998SJonas Devlieghere const uint64_t id = data->GetID(); 18145a27b998SJonas Devlieghere if (m_current_event_id) { 18155a27b998SJonas Devlieghere if (id != *m_current_event_id) 18165a27b998SJonas Devlieghere return; 18175a27b998SJonas Devlieghere if (data->GetCompleted()) 18185a27b998SJonas Devlieghere m_current_event_id.reset(); 18195a27b998SJonas Devlieghere } else { 18205a27b998SJonas Devlieghere m_current_event_id = id; 18215a27b998SJonas Devlieghere } 18225a27b998SJonas Devlieghere 18235a27b998SJonas Devlieghere // Decide whether we actually are going to show the progress. This decision 18245a27b998SJonas Devlieghere // can change between iterations so check it inside the loop. 18255a27b998SJonas Devlieghere if (!GetShowProgress()) 18265a27b998SJonas Devlieghere return; 18275a27b998SJonas Devlieghere 18285a27b998SJonas Devlieghere // Determine whether the current output file is an interactive terminal with 18295a27b998SJonas Devlieghere // color support. We assume that if we support ANSI escape codes we support 18305a27b998SJonas Devlieghere // vt100 escape codes. 1831c231deb7SJonas Devlieghere File &file = GetOutputFile(); 1832c231deb7SJonas Devlieghere if (!file.GetIsInteractive() || !file.GetIsTerminalWithColors()) 18335a27b998SJonas Devlieghere return; 18345a27b998SJonas Devlieghere 1835c231deb7SJonas Devlieghere StreamSP output = GetAsyncOutputStream(); 1836c231deb7SJonas Devlieghere 1837e618eb87SJonas Devlieghere // Print over previous line, if any. 1838c231deb7SJonas Devlieghere output->Printf("\r"); 1839e618eb87SJonas Devlieghere 18405a27b998SJonas Devlieghere if (data->GetCompleted()) { 18415a27b998SJonas Devlieghere // Clear the current line. 1842c231deb7SJonas Devlieghere output->Printf("\x1B[2K"); 1843c231deb7SJonas Devlieghere output->Flush(); 18445a27b998SJonas Devlieghere return; 18455a27b998SJonas Devlieghere } 18465a27b998SJonas Devlieghere 1847097d46f4SJonas Devlieghere const bool use_color = GetUseColor(); 1848097d46f4SJonas Devlieghere llvm::StringRef ansi_prefix = GetShowProgressAnsiPrefix(); 1849097d46f4SJonas Devlieghere if (!ansi_prefix.empty()) 1850c231deb7SJonas Devlieghere output->Printf( 1851097d46f4SJonas Devlieghere "%s", ansi::FormatAnsiTerminalCodes(ansi_prefix, use_color).c_str()); 1852097d46f4SJonas Devlieghere 18535a27b998SJonas Devlieghere // Print the progress message. 18545a27b998SJonas Devlieghere std::string message = data->GetMessage(); 18555a27b998SJonas Devlieghere if (data->GetTotal() != UINT64_MAX) { 1856c231deb7SJonas Devlieghere output->Printf("[%" PRIu64 "/%" PRIu64 "] %s...", data->GetCompleted(), 1857c231deb7SJonas Devlieghere data->GetTotal(), message.c_str()); 18585a27b998SJonas Devlieghere } else { 1859c231deb7SJonas Devlieghere output->Printf("%s...", message.c_str()); 18605a27b998SJonas Devlieghere } 18615a27b998SJonas Devlieghere 1862097d46f4SJonas Devlieghere llvm::StringRef ansi_suffix = GetShowProgressAnsiSuffix(); 1863097d46f4SJonas Devlieghere if (!ansi_suffix.empty()) 1864c231deb7SJonas Devlieghere output->Printf( 1865097d46f4SJonas Devlieghere "%s", ansi::FormatAnsiTerminalCodes(ansi_suffix, use_color).c_str()); 1866097d46f4SJonas Devlieghere 18675a27b998SJonas Devlieghere // Clear until the end of the line. 1868c231deb7SJonas Devlieghere output->Printf("\x1B[K\r"); 18695a27b998SJonas Devlieghere 18705a27b998SJonas Devlieghere // Flush the output. 1871c231deb7SJonas Devlieghere output->Flush(); 18725a27b998SJonas Devlieghere } 18735a27b998SJonas Devlieghere 1874*2fc38b2bSJonas Devlieghere void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) { 1875*2fc38b2bSJonas Devlieghere auto *data = DiagnosticEventData::GetEventDataFromEvent(event_sp.get()); 1876*2fc38b2bSJonas Devlieghere if (!data) 1877*2fc38b2bSJonas Devlieghere return; 1878*2fc38b2bSJonas Devlieghere 1879*2fc38b2bSJonas Devlieghere StreamSP stream = GetAsyncErrorStream(); 1880*2fc38b2bSJonas Devlieghere data->Dump(stream.get()); 1881*2fc38b2bSJonas Devlieghere } 1882*2fc38b2bSJonas Devlieghere 1883b9c1b51eSKate Stone bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } 18846681041dSSean Callanan 1885b9c1b51eSKate Stone bool Debugger::StartIOHandlerThread() { 1886f39c2e18SJonas Devlieghere if (!m_io_handler_thread.IsJoinable()) { 1887f39c2e18SJonas Devlieghere llvm::Expected<HostThread> io_handler_thread = ThreadLauncher::LaunchThread( 1888d0810779SPavel Labath "lldb.debugger.io-handler", [this] { return IOHandlerThread(); }, 1889807b6b32SGreg Clayton 8 * 1024 * 1024); // Use larger 8MB stack for this thread 1890f39c2e18SJonas Devlieghere if (io_handler_thread) { 1891f39c2e18SJonas Devlieghere m_io_handler_thread = *io_handler_thread; 1892f39c2e18SJonas Devlieghere } else { 1893a007a6d8SPavel Labath LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", 1894f39c2e18SJonas Devlieghere llvm::toString(io_handler_thread.takeError())); 1895f39c2e18SJonas Devlieghere } 1896f39c2e18SJonas Devlieghere } 1897acee96aeSZachary Turner return m_io_handler_thread.IsJoinable(); 189844d93782SGreg Clayton } 189944d93782SGreg Clayton 1900b9c1b51eSKate Stone void Debugger::StopIOHandlerThread() { 1901b9c1b51eSKate Stone if (m_io_handler_thread.IsJoinable()) { 19027ca15ba7SLawrence D'Anna GetInputFile().Close(); 190339de3110SZachary Turner m_io_handler_thread.Join(nullptr); 190444d93782SGreg Clayton } 190544d93782SGreg Clayton } 190644d93782SGreg Clayton 1907b9c1b51eSKate Stone void Debugger::JoinIOHandlerThread() { 1908b9c1b51eSKate Stone if (HasIOHandlerThread()) { 19096681041dSSean Callanan thread_result_t result; 19106681041dSSean Callanan m_io_handler_thread.Join(&result); 19116681041dSSean Callanan m_io_handler_thread = LLDB_INVALID_HOST_THREAD; 19126681041dSSean Callanan } 19136681041dSSean Callanan } 19146681041dSSean Callanan 1915b2fa3b92SJonas Devlieghere Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { 1916b9c1b51eSKate Stone if (!prefer_dummy) { 1917b2fa3b92SJonas Devlieghere if (TargetSP target = m_target_list.GetSelectedTarget()) 1918b2fa3b92SJonas Devlieghere return *target; 191933df7cd3SJim Ingham } 1920893c932aSJim Ingham return GetDummyTarget(); 1921893c932aSJim Ingham } 192244d93782SGreg Clayton 192397206d57SZachary Turner Status Debugger::RunREPL(LanguageType language, const char *repl_options) { 192497206d57SZachary Turner Status err; 19253e7e915dSSean Callanan FileSpec repl_executable; 19263e7e915dSSean Callanan 192746a28a95SJonas Devlieghere if (language == eLanguageTypeUnknown) 192846a28a95SJonas Devlieghere language = GetREPLLanguage(); 192946a28a95SJonas Devlieghere 1930b9c1b51eSKate Stone if (language == eLanguageTypeUnknown) { 1931aa97a89dSAdrian Prantl LanguageSet repl_languages = Language::GetLanguagesSupportingREPLs(); 193297f84e87SSean Callanan 1933aa97a89dSAdrian Prantl if (auto single_lang = repl_languages.GetSingularLanguage()) { 1934aa97a89dSAdrian Prantl language = *single_lang; 1935aa97a89dSAdrian Prantl } else if (repl_languages.Empty()) { 193646a28a95SJonas Devlieghere err.SetErrorString( 1937b9c1b51eSKate Stone "LLDB isn't configured with REPL support for any languages."); 193897f84e87SSean Callanan return err; 1939b9c1b51eSKate Stone } else { 194046a28a95SJonas Devlieghere err.SetErrorString( 1941b9c1b51eSKate Stone "Multiple possible REPL languages. Please specify a language."); 194297f84e87SSean Callanan return err; 194397f84e87SSean Callanan } 194497f84e87SSean Callanan } 194597f84e87SSean Callanan 1946b9c1b51eSKate Stone Target *const target = 1947b9c1b51eSKate Stone nullptr; // passing in an empty target means the REPL must create one 19483e7e915dSSean Callanan 19493b682de6SSean Callanan REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); 19503e7e915dSSean Callanan 1951b9c1b51eSKate Stone if (!err.Success()) { 19523e7e915dSSean Callanan return err; 19533e7e915dSSean Callanan } 19543e7e915dSSean Callanan 1955b9c1b51eSKate Stone if (!repl_sp) { 1956b9c1b51eSKate Stone err.SetErrorStringWithFormat("couldn't find a REPL for %s", 1957b9c1b51eSKate Stone Language::GetNameForLanguageType(language)); 19583e7e915dSSean Callanan return err; 19593e7e915dSSean Callanan } 19603e7e915dSSean Callanan 19613e7e915dSSean Callanan repl_sp->SetCompilerOptions(repl_options); 19623e7e915dSSean Callanan repl_sp->RunLoop(); 19633e7e915dSSean Callanan 19643e7e915dSSean Callanan return err; 19653e7e915dSSean Callanan } 1966