aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core/Debugger.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-07-26 19:03:47 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-07-26 19:04:23 +0000
commit7fa27ce4a07f19b07799a767fc29416f3b625afb (patch)
tree27825c83636c4de341eb09a74f49f5d38a15d165 /lldb/source/Core/Debugger.cpp
parente3b557809604d036af6e00c60f012c2025b59a5e (diff)
Diffstat (limited to 'lldb/source/Core/Debugger.cpp')
-rw-r--r--lldb/source/Core/Debugger.cpp432
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())