aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Core/Debugger.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /lldb/source/Core/Debugger.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'lldb/source/Core/Debugger.cpp')
-rw-r--r--lldb/source/Core/Debugger.cpp138
1 files changed, 77 insertions, 61 deletions
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 62857c181af8..8a8a01c70ce6 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -13,6 +13,7 @@
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StreamAsynchronousIO.h"
#include "lldb/Core/StreamFile.h"
@@ -43,22 +44,21 @@
#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"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Reproducer.h"
-#include "lldb/Utility/ReproducerProvider.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-enumerations.h"
#if defined(_WIN32)
#include "lldb/Host/windows/PosixApi.h"
#include "lldb/Host/windows/windows.h"
#endif
-#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
@@ -75,6 +75,7 @@
#include <list>
#include <memory>
#include <mutex>
+#include <optional>
#include <set>
#include <string>
#include <system_error>
@@ -104,6 +105,7 @@ 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 =
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
+static llvm::ThreadPool *g_thread_pool = nullptr;
static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
{
@@ -148,6 +150,16 @@ static constexpr OptionEnumValueElement g_language_enumerators[] = {
},
};
+static constexpr OptionEnumValueElement g_dwim_print_verbosities[] = {
+ {eDWIMPrintVerbosityNone, "none",
+ "Use no verbosity when running dwim-print."},
+ {eDWIMPrintVerbosityExpression, "expression",
+ "Use partial verbosity when running dwim-print - display a message when "
+ "`expression` evaluation is used."},
+ {eDWIMPrintVerbosityFull, "full",
+ "Use full verbosity when running dwim-print."},
+};
+
static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
{
eStopShowColumnAnsiOrCaret,
@@ -201,7 +213,7 @@ Status Debugger::SetPropertyValue(const ExecutionContext *exe_ctx,
}
TargetSP target_sp;
- LoadScriptFromSymFile load_script_old_value;
+ LoadScriptFromSymFile load_script_old_value = eLoadScriptFromSymFileFalse;
if (is_load_script && exe_ctx->GetTargetSP()) {
target_sp = exe_ctx->GetTargetSP();
load_script_old_value =
@@ -300,11 +312,6 @@ void Debugger::SetPrompt(llvm::StringRef p) {
GetCommandInterpreter().UpdatePrompt(new_prompt);
}
-llvm::StringRef Debugger::GetReproducerPath() const {
- auto &r = repro::Reproducer::Instance();
- return r.GetReproducerPath().GetCString();
-}
-
const FormatEntity::Entry *Debugger::GetThreadFormat() const {
const uint32_t idx = ePropertyThreadFormat;
return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
@@ -524,6 +531,13 @@ bool Debugger::SetTabSize(uint32_t tab_size) {
return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, 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);
+}
+
#pragma mark Debugger
// const DebuggerPropertiesSP &
@@ -538,6 +552,7 @@ void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) {
"Debugger::Initialize called more than once!");
g_debugger_list_mutex_ptr = new std::recursive_mutex();
g_debugger_list_ptr = new DebuggerList();
+ g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency());
g_load_plugin_callback = load_plugin_callback;
}
@@ -545,6 +560,11 @@ void Debugger::Terminate() {
assert(g_debugger_list_ptr &&
"Debugger::Terminate called without a matching Debugger::Initialize!");
+ if (g_thread_pool) {
+ // The destructor will wait for all the threads to complete.
+ delete g_thread_pool;
+ }
+
if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
// Clear our global list of debugger objects
{
@@ -916,42 +936,12 @@ Status Debugger::SetInputString(const char *data) {
return result;
}
- return SetInputFile(
- (FileSP)std::make_shared<NativeFile>(commands_file, true));
+ SetInputFile((FileSP)std::make_shared<NativeFile>(commands_file, true));
+ return result;
}
-Status Debugger::SetInputFile(FileSP file_sp) {
- Status error;
- repro::DataRecorder *recorder = nullptr;
- if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator())
- recorder = g->GetOrCreate<repro::CommandProvider>().GetNewRecorder();
-
- static std::unique_ptr<repro::MultiLoader<repro::CommandProvider>> loader =
- repro::MultiLoader<repro::CommandProvider>::Create(
- repro::Reproducer::Instance().GetLoader());
- if (loader) {
- llvm::Optional<std::string> nextfile = loader->GetNextFile();
- FILE *fh = nextfile ? FileSystem::Instance().Fopen(nextfile->c_str(), "r")
- : nullptr;
- // FIXME Jonas Devlieghere: shouldn't this error be propagated out to the
- // reproducer somehow if fh is NULL?
- if (fh) {
- file_sp = std::make_shared<NativeFile>(fh, true);
- }
- }
-
- if (!file_sp || !file_sp->IsValid()) {
- error.SetErrorString("invalid file");
- return error;
- }
-
- SetInputFile(file_sp, recorder);
- return error;
-}
-
-void Debugger::SetInputFile(FileSP file_sp, repro::DataRecorder *recorder) {
+void Debugger::SetInputFile(FileSP file_sp) {
assert(file_sp && file_sp->IsValid());
- m_input_recorder = recorder;
m_input_file_sp = std::move(file_sp);
// Save away the terminal state if that is relevant, so that we can restore
// it in RestoreInputState.
@@ -1311,7 +1301,7 @@ static void PrivateReportProgress(Debugger &debugger, uint64_t progress_id,
void Debugger::ReportProgress(uint64_t progress_id, const std::string &message,
uint64_t completed, uint64_t total,
- llvm::Optional<lldb::user_id_t> debugger_id) {
+ std::optional<lldb::user_id_t> debugger_id) {
// Check if this progress is for a specific debugger.
if (debugger_id) {
// It is debugger specific, grab it and deliver the event if the debugger
@@ -1339,6 +1329,9 @@ static void PrivateReportDiagnostic(Debugger &debugger,
bool debugger_specific) {
uint32_t event_type = 0;
switch (type) {
+ case DiagnosticEventData::Type::Info:
+ assert(false && "DiagnosticEventData::Type::Info should not be broadcast");
+ return;
case DiagnosticEventData::Type::Warning:
event_type = Debugger::eBroadcastBitWarning;
break;
@@ -1364,10 +1357,19 @@ static void PrivateReportDiagnostic(Debugger &debugger,
void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
std::string message,
- llvm::Optional<lldb::user_id_t> debugger_id,
+ std::optional<lldb::user_id_t> debugger_id,
std::once_flag *once) {
auto ReportDiagnosticLambda = [&]() {
- // Check if this progress is for a specific debugger.
+ // The diagnostic subsystem is optional but we still want to broadcast
+ // events when it's disabled.
+ if (Diagnostics::Enabled())
+ Diagnostics::Instance().Report(message);
+
+ // We don't broadcast info events.
+ if (type == DiagnosticEventData::Type::Info)
+ return;
+
+ // Check if this diagnostic is for a specific debugger.
if (debugger_id) {
// It is debugger specific, grab it and deliver the event if the debugger
// still exists.
@@ -1376,8 +1378,8 @@ void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
PrivateReportDiagnostic(*debugger_sp, type, std::move(message), true);
return;
}
- // The progress event is not debugger specific, iterate over all debuggers
- // and deliver a progress event to each one.
+ // The diagnostic event is not debugger specific, iterate over all debuggers
+ // and deliver a diagnostic event to each one.
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)
@@ -1392,20 +1394,38 @@ void Debugger::ReportDiagnosticImpl(DiagnosticEventData::Type type,
}
void Debugger::ReportWarning(std::string message,
- llvm::Optional<lldb::user_id_t> debugger_id,
+ std::optional<lldb::user_id_t> debugger_id,
std::once_flag *once) {
ReportDiagnosticImpl(DiagnosticEventData::Type::Warning, std::move(message),
debugger_id, once);
}
void Debugger::ReportError(std::string message,
- llvm::Optional<lldb::user_id_t> debugger_id,
+ std::optional<lldb::user_id_t> debugger_id,
std::once_flag *once) {
-
ReportDiagnosticImpl(DiagnosticEventData::Type::Error, std::move(message),
debugger_id, once);
}
+void Debugger::ReportInfo(std::string message,
+ std::optional<lldb::user_id_t> debugger_id,
+ std::once_flag *once) {
+ ReportDiagnosticImpl(DiagnosticEventData::Type::Info, std::move(message),
+ debugger_id, once);
+}
+
+void Debugger::ReportSymbolChange(const ModuleSpec &module_spec) {
+ if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) {
+ std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr);
+ for (DebuggerSP debugger_sp : *g_debugger_list_ptr) {
+ EventSP event_sp = std::make_shared<Event>(
+ Debugger::eBroadcastSymbolChange,
+ new SymbolChangeEventData(debugger_sp, module_spec));
+ debugger_sp->GetBroadcaster().BroadcastEvent(event_sp);
+ }
+ }
+}
+
static std::shared_ptr<LogHandler>
CreateLogHandler(LogHandlerKind log_handler_kind, int fd, bool should_close,
size_t buffer_size) {
@@ -1474,7 +1494,7 @@ bool Debugger::EnableLog(llvm::StringRef channel,
ScriptInterpreter *
Debugger::GetScriptInterpreter(bool can_create,
- llvm::Optional<lldb::ScriptLanguage> language) {
+ std::optional<lldb::ScriptLanguage> language) {
std::lock_guard<std::recursive_mutex> locker(m_script_interpreter_mutex);
lldb::ScriptLanguage script_language =
language ? *language : GetScriptLanguage();
@@ -1702,8 +1722,8 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
CommandInterpreter::eBroadcastBitAsynchronousErrorData);
listener_sp->StartListeningForEvents(
- &m_broadcaster,
- eBroadcastBitProgress | eBroadcastBitWarning | eBroadcastBitError);
+ &m_broadcaster, eBroadcastBitProgress | eBroadcastBitWarning |
+ eBroadcastBitError | eBroadcastSymbolChange);
// Let the thread that spawned us know that we have started up and that we
// are now listening to all required events so no events get missed
@@ -1712,7 +1732,7 @@ lldb::thread_result_t Debugger::DefaultEventHandler() {
bool done = false;
while (!done) {
EventSP event_sp;
- if (listener_sp->GetEvent(event_sp, llvm::None)) {
+ if (listener_sp->GetEvent(event_sp, std::nullopt)) {
if (event_sp) {
Broadcaster *broadcaster = event_sp->GetBroadcaster();
if (broadcaster) {
@@ -1807,7 +1827,7 @@ bool Debugger::StartEventHandlerThread() {
// event, we just need to wait an infinite amount of time for it (nullptr
// timeout as the first parameter)
lldb::EventSP event_sp;
- listener_sp->GetEvent(event_sp, llvm::None);
+ listener_sp->GetEvent(event_sp, std::nullopt);
}
return m_event_handler_thread.IsJoinable();
}
@@ -2005,11 +2025,7 @@ Status Debugger::RunREPL(LanguageType language, const char *repl_options) {
}
llvm::ThreadPool &Debugger::GetThreadPool() {
- // NOTE: intentional leak to avoid issues with C++ destructor chain
- static llvm::ThreadPool *g_thread_pool = nullptr;
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, []() {
- g_thread_pool = new llvm::ThreadPool(llvm::optimal_concurrency());
- });
+ assert(g_thread_pool &&
+ "Debugger::GetThreadPool called before Debugger::Initialize");
return *g_thread_pool;
}