diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:03:47 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-07-26 19:04:23 +0000 |
| commit | 7fa27ce4a07f19b07799a767fc29416f3b625afb (patch) | |
| tree | 27825c83636c4de341eb09a74f49f5d38a15d165 /lldb/source/Core/Debugger.cpp | |
| parent | e3b557809604d036af6e00c60f012c2025b59a5e (diff) | |
Diffstat (limited to 'lldb/source/Core/Debugger.cpp')
| -rw-r--r-- | lldb/source/Core/Debugger.cpp | 432 |
1 files changed, 285 insertions, 147 deletions
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 8a8a01c70ce6..f54108629185 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -44,7 +44,6 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadList.h" #include "lldb/Utility/AnsiTerminal.h" -#include "lldb/Utility/Diagnostics.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Listener.h" @@ -100,10 +99,9 @@ static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; #pragma mark Static Functions -typedef std::vector<DebuggerSP> DebuggerList; static std::recursive_mutex *g_debugger_list_mutex_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain -static DebuggerList *g_debugger_list_ptr = +static Debugger::DebuggerList *g_debugger_list_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain static llvm::ThreadPool *g_thread_pool = nullptr; @@ -214,7 +212,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, TargetSP target_sp; LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse; - if (is_load_script && exe_ctx->GetTargetSP()) { + if (is_load_script && exe_ctx && exe_ctx->GetTargetSP()) { target_sp = exe_ctx->GetTargetSP(); load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); @@ -237,8 +235,10 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, // use-color changed. Ping the prompt so it can reset the ansi terminal // codes. SetPrompt(GetPrompt()); - } else if (property_path == g_debugger_properties[ePropertyUseSourceCache].name) { - // use-source-cache changed. Wipe out the cache contents if it was disabled. + } else if (property_path == + g_debugger_properties[ePropertyUseSourceCache].name) { + // use-source-cache changed. Wipe out the cache contents if it was + // disabled. if (!GetUseSourceCache()) { m_source_file_cache.Clear(); } @@ -248,7 +248,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, eLoadScriptFromSymFileTrue) { std::list<Status> errors; StreamString feedback_stream; - if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { + if (!target_sp->LoadScriptingResources(errors, feedback_stream)) { Stream &s = GetErrorStream(); for (auto error : errors) { s.Printf("%s\n", error.AsCString()); @@ -263,47 +263,47 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, } bool Debugger::GetAutoConfirm() const { - const uint32_t idx = ePropertyAutoConfirm; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + constexpr uint32_t idx = ePropertyAutoConfirm; + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { - const uint32_t idx = ePropertyDisassemblyFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); + constexpr uint32_t idx = ePropertyDisassemblyFormat; + return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); } const FormatEntity::Entry *Debugger::GetFrameFormat() const { - const uint32_t idx = ePropertyFrameFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); + constexpr uint32_t idx = ePropertyFrameFormat; + return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); } const FormatEntity::Entry *Debugger::GetFrameFormatUnique() const { - const uint32_t idx = ePropertyFrameFormatUnique; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); + constexpr uint32_t idx = ePropertyFrameFormatUnique; + return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); } -uint32_t Debugger::GetStopDisassemblyMaxSize() const { - const uint32_t idx = ePropertyStopDisassemblyMaxSize; - return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_debugger_properties[idx].default_uint_value); +uint64_t Debugger::GetStopDisassemblyMaxSize() const { + constexpr uint32_t idx = ePropertyStopDisassemblyMaxSize; + return GetPropertyAtIndexAs<uint64_t>( + idx, g_debugger_properties[idx].default_uint_value); } bool Debugger::GetNotifyVoid() const { - const uint32_t idx = ePropertyNotiftVoid; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + constexpr uint32_t idx = ePropertyNotiftVoid; + return GetPropertyAtIndexAs<uint64_t>( + idx, g_debugger_properties[idx].default_uint_value != 0); } llvm::StringRef Debugger::GetPrompt() const { - const uint32_t idx = ePropertyPrompt; - return m_collection_sp->GetPropertyAtIndexAsString( - nullptr, idx, g_debugger_properties[idx].default_cstr_value); + constexpr uint32_t idx = ePropertyPrompt; + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } void Debugger::SetPrompt(llvm::StringRef p) { - const uint32_t idx = ePropertyPrompt; - m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); + constexpr uint32_t idx = ePropertyPrompt; + SetPropertyAtIndex(idx, p); llvm::StringRef new_prompt = GetPrompt(); std::string str = lldb_private::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); @@ -313,126 +313,136 @@ void Debugger::SetPrompt(llvm::StringRef p) { } const FormatEntity::Entry *Debugger::GetThreadFormat() const { - const uint32_t idx = ePropertyThreadFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); + constexpr uint32_t idx = ePropertyThreadFormat; + return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); } const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { - const uint32_t idx = ePropertyThreadStopFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); + constexpr uint32_t idx = ePropertyThreadStopFormat; + return GetPropertyAtIndexAs<const FormatEntity::Entry *>(idx); } lldb::ScriptLanguage Debugger::GetScriptLanguage() const { const uint32_t idx = ePropertyScriptLanguage; - return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<lldb::ScriptLanguage>( + idx, static_cast<lldb::ScriptLanguage>( + g_debugger_properties[idx].default_uint_value)); } bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { const uint32_t idx = ePropertyScriptLanguage; - return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, - script_lang); + return SetPropertyAtIndex(idx, script_lang); } lldb::LanguageType Debugger::GetREPLLanguage() const { const uint32_t idx = ePropertyREPLLanguage; - OptionValueLanguage *value = - m_collection_sp->GetPropertyAtIndexAsOptionValueLanguage(nullptr, idx); - if (value) - return value->GetCurrentValue(); - return LanguageType(); + return GetPropertyAtIndexAs<LanguageType>(idx, {}); } bool Debugger::SetREPLLanguage(lldb::LanguageType repl_lang) { const uint32_t idx = ePropertyREPLLanguage; - return m_collection_sp->SetPropertyAtIndexAsLanguage(nullptr, idx, repl_lang); + return SetPropertyAtIndex(idx, repl_lang); } -uint32_t Debugger::GetTerminalWidth() const { +uint64_t Debugger::GetTerminalWidth() const { const uint32_t idx = ePropertyTerminalWidth; - return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<int64_t>( + idx, g_debugger_properties[idx].default_uint_value); } -bool Debugger::SetTerminalWidth(uint32_t term_width) { +bool Debugger::SetTerminalWidth(uint64_t term_width) { if (auto handler_sp = m_io_handler_stack.Top()) handler_sp->TerminalSizeChanged(); const uint32_t idx = ePropertyTerminalWidth; - return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); + return SetPropertyAtIndex(idx, term_width); } bool Debugger::GetUseExternalEditor() const { const uint32_t idx = ePropertyUseExternalEditor; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetUseExternalEditor(bool b) { const uint32_t idx = ePropertyUseExternalEditor; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); + return SetPropertyAtIndex(idx, b); +} + +llvm::StringRef Debugger::GetExternalEditor() const { + const uint32_t idx = ePropertyExternalEditor; + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); +} + +bool Debugger::SetExternalEditor(llvm::StringRef editor) { + const uint32_t idx = ePropertyExternalEditor; + return SetPropertyAtIndex(idx, editor); } bool Debugger::GetUseColor() const { const uint32_t idx = ePropertyUseColor; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetUseColor(bool b) { const uint32_t idx = ePropertyUseColor; - bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); + bool ret = SetPropertyAtIndex(idx, b); SetPrompt(GetPrompt()); return ret; } bool Debugger::GetShowProgress() const { const uint32_t idx = ePropertyShowProgress; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetShowProgress(bool show_progress) { const uint32_t idx = ePropertyShowProgress; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, - show_progress); + return SetPropertyAtIndex(idx, show_progress); } llvm::StringRef Debugger::GetShowProgressAnsiPrefix() const { const uint32_t idx = ePropertyShowProgressAnsiPrefix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } llvm::StringRef Debugger::GetShowProgressAnsiSuffix() const { const uint32_t idx = ePropertyShowProgressAnsiSuffix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } bool Debugger::GetUseAutosuggestion() const { const uint32_t idx = ePropertyShowAutosuggestion; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } llvm::StringRef Debugger::GetAutosuggestionAnsiPrefix() const { const uint32_t idx = ePropertyShowAutosuggestionAnsiPrefix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const { const uint32_t idx = ePropertyShowAutosuggestionAnsiSuffix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } bool Debugger::GetUseSourceCache() const { const uint32_t idx = ePropertyUseSourceCache; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value != 0); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetUseSourceCache(bool b) { const uint32_t idx = ePropertyUseSourceCache; - bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); + bool ret = SetPropertyAtIndex(idx, b); if (!ret) { m_source_file_cache.Clear(); } @@ -440,102 +450,111 @@ bool Debugger::SetUseSourceCache(bool b) { } bool Debugger::GetHighlightSource() const { const uint32_t idx = ePropertyHighlightSource; - return m_collection_sp->GetPropertyAtIndexAsBoolean( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } StopShowColumn Debugger::GetStopShowColumn() const { const uint32_t idx = ePropertyStopShowColumn; - return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<lldb::StopShowColumn>( + idx, static_cast<lldb::StopShowColumn>( + g_debugger_properties[idx].default_uint_value)); } llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const { const uint32_t idx = ePropertyStopShowColumnAnsiPrefix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const { const uint32_t idx = ePropertyStopShowColumnAnsiSuffix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } llvm::StringRef Debugger::GetStopShowLineMarkerAnsiPrefix() const { const uint32_t idx = ePropertyStopShowLineMarkerAnsiPrefix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } llvm::StringRef Debugger::GetStopShowLineMarkerAnsiSuffix() const { const uint32_t idx = ePropertyStopShowLineMarkerAnsiSuffix; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, ""); + return GetPropertyAtIndexAs<llvm::StringRef>( + idx, g_debugger_properties[idx].default_cstr_value); } -uint32_t Debugger::GetStopSourceLineCount(bool before) const { +uint64_t Debugger::GetStopSourceLineCount(bool before) const { const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; - return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<uint64_t>( + idx, g_debugger_properties[idx].default_uint_value); } Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { const uint32_t idx = ePropertyStopDisassemblyDisplay; - return (Debugger::StopDisassemblyType) - m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<Debugger::StopDisassemblyType>( + idx, static_cast<Debugger::StopDisassemblyType>( + g_debugger_properties[idx].default_uint_value)); } -uint32_t Debugger::GetDisassemblyLineCount() const { +uint64_t Debugger::GetDisassemblyLineCount() const { const uint32_t idx = ePropertyStopDisassemblyCount; - return m_collection_sp->GetPropertyAtIndexAsSInt64( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<uint64_t>( + idx, g_debugger_properties[idx].default_uint_value); } bool Debugger::GetAutoOneLineSummaries() const { const uint32_t idx = ePropertyAutoOneLineSummaries; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::GetEscapeNonPrintables() const { const uint32_t idx = ePropertyEscapeNonPrintables; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::GetAutoIndent() const { const uint32_t idx = ePropertyAutoIndent; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetAutoIndent(bool b) { const uint32_t idx = ePropertyAutoIndent; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); + return SetPropertyAtIndex(idx, b); } bool Debugger::GetPrintDecls() const { const uint32_t idx = ePropertyPrintDecls; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); + return GetPropertyAtIndexAs<bool>( + idx, g_debugger_properties[idx].default_uint_value != 0); } bool Debugger::SetPrintDecls(bool b) { const uint32_t idx = ePropertyPrintDecls; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); + return SetPropertyAtIndex(idx, b); } -uint32_t Debugger::GetTabSize() const { +uint64_t Debugger::GetTabSize() const { const uint32_t idx = ePropertyTabSize; - return m_collection_sp->GetPropertyAtIndexAsUInt64( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<uint64_t>( + idx, g_debugger_properties[idx].default_uint_value); } -bool Debugger::SetTabSize(uint32_t tab_size) { +bool Debugger::SetTabSize(uint64_t tab_size) { const uint32_t idx = ePropertyTabSize; - return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); + return SetPropertyAtIndex(idx, tab_size); } lldb::DWIMPrintVerbosity Debugger::GetDWIMPrintVerbosity() const { const uint32_t idx = ePropertyDWIMPrintVerbosity; - return (lldb::DWIMPrintVerbosity) - m_collection_sp->GetPropertyAtIndexAsEnumeration( - nullptr, idx, g_debugger_properties[idx].default_uint_value); + return GetPropertyAtIndexAs<lldb::DWIMPrintVerbosity>( + idx, static_cast<lldb::DWIMPrintVerbosity>( + g_debugger_properties[idx].default_uint_value)); } #pragma mark Debugger @@ -560,6 +579,12 @@ void Debugger::Terminate() { assert(g_debugger_list_ptr && "Debugger::Terminate called without a matching Debugger::Initialize!"); + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + for (const auto &debugger : *g_debugger_list_ptr) + debugger->HandleDestroyCallback(); + } + if (g_thread_pool) { // The destructor will wait for all the threads to complete. delete g_thread_pool; @@ -602,8 +627,8 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) { Status error; - static ConstString g_dylibext(".dylib"); - static ConstString g_solibext(".so"); + static constexpr llvm::StringLiteral g_dylibext(".dylib"); + static constexpr llvm::StringLiteral g_solibext(".so"); if (!baton) return FileSystem::eEnumerateDirectoryResultQuit; @@ -679,10 +704,18 @@ DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, return debugger_sp; } +void Debugger::HandleDestroyCallback() { + if (m_destroy_callback) { + m_destroy_callback(GetID(), m_destroy_callback_baton); + m_destroy_callback = nullptr; + } +} + void Debugger::Destroy(DebuggerSP &debugger_sp) { if (!debugger_sp) return; + debugger_sp->HandleDestroyCallback(); CommandInterpreter &cmd_interpreter = debugger_sp->GetCommandInterpreter(); if (cmd_interpreter.GetSaveSessionOnQuit()) { @@ -708,19 +741,20 @@ void Debugger::Destroy(DebuggerSP &debugger_sp) { } } -DebuggerSP Debugger::FindDebuggerWithInstanceName(ConstString instance_name) { - DebuggerSP debugger_sp; - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); - for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { - if ((*pos)->m_instance_name == instance_name) { - debugger_sp = *pos; - break; - } - } +DebuggerSP +Debugger::FindDebuggerWithInstanceName(llvm::StringRef instance_name) { + if (!g_debugger_list_ptr || !g_debugger_list_mutex_ptr) + return DebuggerSP(); + + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + for (const DebuggerSP &debugger_sp : *g_debugger_list_ptr) { + if (!debugger_sp) + continue; + + if (llvm::StringRef(debugger_sp->GetInstanceName()) == instance_name) + return debugger_sp; } - return debugger_sp; + return DebuggerSP(); } TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) { @@ -769,13 +803,31 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) m_source_manager_up(), m_source_file_cache(), m_command_interpreter_up( std::make_unique<CommandInterpreter>(*this, false)), - m_io_handler_stack(), m_instance_name(), m_loaded_plugins(), - m_event_handler_thread(), m_io_handler_thread(), + m_io_handler_stack(), + m_instance_name(llvm::formatv("debugger_{0}", GetID()).str()), + m_loaded_plugins(), m_event_handler_thread(), m_io_handler_thread(), m_sync_broadcaster(nullptr, "lldb.debugger.sync"), m_broadcaster(m_broadcaster_manager_sp, GetStaticBroadcasterClass().AsCString()), m_forward_listener_sp(), m_clear_once() { - m_instance_name.SetString(llvm::formatv("debugger_{0}", GetID()).str()); + // Initialize the debugger properties as early as possible as other parts of + // LLDB will start querying them during construction. + m_collection_sp->Initialize(g_debugger_properties); + m_collection_sp->AppendProperty( + "target", "Settings specify to debugging targets.", true, + Target::GetGlobalProperties().GetValueProperties()); + m_collection_sp->AppendProperty( + "platform", "Platform settings.", true, + Platform::GetGlobalPlatformProperties().GetValueProperties()); + m_collection_sp->AppendProperty( + "symbols", "Symbol lookup and cache settings.", true, + ModuleList::GetGlobalModuleListProperties().GetValueProperties()); + if (m_command_interpreter_up) { + m_collection_sp->AppendProperty( + "interpreter", + "Settings specify to the debugger's command interpreter.", true, + m_command_interpreter_up->GetValueProperties()); + } if (log_callback) m_callback_handler_sp = std::make_shared<CallbackLogHandler>(log_callback, baton); @@ -797,26 +849,9 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) } assert(m_dummy_target_sp.get() && "Couldn't construct dummy target?"); - m_collection_sp->Initialize(g_debugger_properties); - m_collection_sp->AppendProperty( - ConstString("target"), - ConstString("Settings specify to debugging targets."), true, - Target::GetGlobalProperties().GetValueProperties()); - m_collection_sp->AppendProperty( - ConstString("platform"), ConstString("Platform settings."), true, - Platform::GetGlobalPlatformProperties().GetValueProperties()); - m_collection_sp->AppendProperty( - ConstString("symbols"), ConstString("Symbol lookup and cache settings."), - true, ModuleList::GetGlobalModuleListProperties().GetValueProperties()); - if (m_command_interpreter_up) { - m_collection_sp->AppendProperty( - ConstString("interpreter"), - ConstString("Settings specify to the debugger's command interpreter."), - true, m_command_interpreter_up->GetValueProperties()); - } OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64( - nullptr, ePropertyTerminalWidth); + ePropertyTerminalWidth); term_width->SetMinimumValue(10); term_width->SetMaximumValue(1024); @@ -828,6 +863,22 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) if (!GetOutputFile().GetIsTerminalWithColors()) SetUseColor(false); + if (Diagnostics::Enabled()) { + m_diagnostics_callback_id = Diagnostics::Instance().AddCallback( + [this](const FileSpec &dir) -> llvm::Error { + for (auto &entry : m_stream_handlers) { + llvm::StringRef log_path = entry.first(); + llvm::StringRef file_name = llvm::sys::path::filename(log_path); + FileSpec destination = dir.CopyByAppendingPathComponent(file_name); + std::error_code ec = + llvm::sys::fs::copy_file(log_path, destination.GetPath()); + if (ec) + return llvm::errorCodeToError(ec); + } + return llvm::Error::success(); + }); + } + #if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING) // Enabling use of ANSI color codes because LLDB is using them to highlight // text. @@ -866,6 +917,9 @@ void Debugger::Clear() { GetInputFile().Close(); m_command_interpreter_up->Clear(); + + if (Diagnostics::Enabled()) + Diagnostics::Instance().RemoveCallback(m_diagnostics_callback_id); }); } @@ -1074,7 +1128,7 @@ void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { } } -ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { +llvm::StringRef Debugger::GetTopIOHandlerControlSequence(char ch) { return m_io_handler_stack.GetTopIOHandlerControlSequence(ch); } @@ -1198,6 +1252,56 @@ StreamSP Debugger::GetAsyncErrorStream() { return std::make_shared<StreamAsynchronousIO>(*this, false, GetUseColor()); } +void Debugger::RequestInterrupt() { + std::lock_guard<std::mutex> guard(m_interrupt_mutex); + m_interrupt_requested++; +} + +void Debugger::CancelInterruptRequest() { + std::lock_guard<std::mutex> guard(m_interrupt_mutex); + if (m_interrupt_requested > 0) + m_interrupt_requested--; +} + +bool Debugger::InterruptRequested() { + // This is the one we should call internally. This will return true either + // if there's a debugger interrupt and we aren't on the IOHandler thread, + // or if we are on the IOHandler thread and there's a CommandInterpreter + // interrupt. + if (!IsIOHandlerThreadCurrentThread()) { + std::lock_guard<std::mutex> guard(m_interrupt_mutex); + return m_interrupt_requested != 0; + } + return GetCommandInterpreter().WasInterrupted(); +} + +Debugger::InterruptionReport::InterruptionReport(std::string function_name, + const llvm::formatv_object_base &payload) : + m_function_name(std::move(function_name)), + m_interrupt_time(std::chrono::system_clock::now()), + m_thread_id(llvm::get_threadid()) { + llvm::raw_string_ostream desc(m_description); + desc << payload << "\n"; +} + +void Debugger::ReportInterruption(const InterruptionReport &report) { + // For now, just log the description: + Log *log = GetLog(LLDBLog::Host); + LLDB_LOG(log, "Interruption: {0}", report.m_description); +} + +Debugger::DebuggerList Debugger::DebuggersRequestingInterruption() { + DebuggerList result; + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + for (auto debugger_sp : *g_debugger_list_ptr) { + if (debugger_sp->InterruptRequested()) + result.push_back(debugger_sp); + } + } + return result; +} + size_t Debugger::GetNumDebuggers() { if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); @@ -1276,6 +1380,13 @@ bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, function_changed, initial_function); } +void Debugger::AssertCallback(llvm::StringRef message, + llvm::StringRef backtrace, + llvm::StringRef prompt) { + Debugger::ReportError( + llvm::formatv("{0}\n{1}{2}", message, backtrace, prompt).str()); +} + void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton) { // For simplicity's sake, I am not going to deal with how to close down any @@ -1285,8 +1396,14 @@ void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, std::make_shared<CallbackLogHandler>(log_callback, baton); } +void Debugger::SetDestroyCallback( + lldb_private::DebuggerDestroyCallback destroy_callback, void *baton) { + m_destroy_callback = destroy_callback; + m_destroy_callback_baton = baton; +} + static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, - const std::string &message, + std::string title, std::string details, uint64_t completed, uint64_t total, bool is_debugger_specific) { // Only deliver progress events if we have any progress listeners. @@ -1294,13 +1411,15 @@ static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id, if (!debugger.GetBroadcaster().EventTypeHasListeners(event_type)) return; EventSP event_sp(new Event( - event_type, new ProgressEventData(progress_id, message, completed, total, - is_debugger_specific))); + event_type, + new ProgressEventData(progress_id, std::move(title), std::move(details), + completed, total, is_debugger_specific))); debugger.GetBroadcaster().BroadcastEvent(event_sp); } -void Debugger::ReportProgress(uint64_t progress_id, const std::string &message, - uint64_t completed, uint64_t total, +void Debugger::ReportProgress(uint64_t progress_id, std::string title, + std::string details, uint64_t completed, + uint64_t total, std::optional<lldb::user_id_t> debugger_id) { // Check if this progress is for a specific debugger. if (debugger_id) { @@ -1308,8 +1427,9 @@ void Debugger::ReportProgress(uint64_t progress_id, const std::string &message, // still exists. DebuggerSP debugger_sp = FindDebuggerWithID(*debugger_id); if (debugger_sp) - PrivateReportProgress(*debugger_sp, progress_id, message, completed, - total, /*is_debugger_specific*/ true); + PrivateReportProgress(*debugger_sp, progress_id, std::move(title), + std::move(details), completed, total, + /*is_debugger_specific*/ true); return; } // The progress event is not debugger specific, iterate over all debuggers @@ -1318,8 +1438,8 @@ void Debugger::ReportProgress(uint64_t progress_id, const std::string &message, std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) - PrivateReportProgress(*(*pos), progress_id, message, completed, total, - /*is_debugger_specific*/ false); + PrivateReportProgress(*(*pos), progress_id, title, details, completed, + total, /*is_debugger_specific*/ false); } } @@ -1615,7 +1735,10 @@ void Debugger::HandleProcessEvent(const EventSP &event_sp) { // Display running state changes first before any STDIO if (got_state_changed && !state_is_stopped) { + // This is a public stop which we are going to announce to the user, so + // we should force the most relevant frame selection here. Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), + SelectMostRelevantFrame, pop_process_io_handler); } @@ -1655,6 +1778,7 @@ void Debugger::HandleProcessEvent(const EventSP &event_sp) { // Now display any stopped state changes after any STDIO if (got_state_changed && state_is_stopped) { Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), + SelectMostRelevantFrame, pop_process_io_handler); } @@ -1817,8 +1941,8 @@ bool Debugger::StartEventHandlerThread() { if (event_handler_thread) { m_event_handler_thread = *event_handler_thread; } else { - LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", - llvm::toString(event_handler_thread.takeError())); + LLDB_LOG_ERROR(GetLog(LLDBLog::Host), event_handler_thread.takeError(), + "failed to launch host thread: {0}"); } // Make sure DefaultEventHandler() is running and listening to events @@ -1940,7 +2064,15 @@ void Debugger::HandleDiagnosticEvent(const lldb::EventSP &event_sp) { data->Dump(stream.get()); } -bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } +bool Debugger::HasIOHandlerThread() const { + return m_io_handler_thread.IsJoinable(); +} + +HostThread Debugger::SetIOHandlerThread(HostThread &new_thread) { + HostThread old_host = m_io_handler_thread; + m_io_handler_thread = new_thread; + return old_host; +} bool Debugger::StartIOHandlerThread() { if (!m_io_handler_thread.IsJoinable()) { @@ -1950,8 +2082,8 @@ bool Debugger::StartIOHandlerThread() { if (io_handler_thread) { m_io_handler_thread = *io_handler_thread; } else { - LLDB_LOG(GetLog(LLDBLog::Host), "failed to launch host thread: {}", - llvm::toString(io_handler_thread.takeError())); + LLDB_LOG_ERROR(GetLog(LLDBLog::Host), io_handler_thread.takeError(), + "failed to launch host thread: {0}"); } } return m_io_handler_thread.IsJoinable(); @@ -1972,6 +2104,12 @@ void Debugger::JoinIOHandlerThread() { } } +bool Debugger::IsIOHandlerThreadCurrentThread() const { + if (!HasIOHandlerThread()) + return false; + return m_io_handler_thread.EqualsThread(Host::GetCurrentThread()); +} + Target &Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { if (!prefer_dummy) { if (TargetSP target = m_target_list.GetSelectedTarget()) |
