diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
| commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
| tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /lldb/source/Core/Debugger.cpp | |
| parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) | |
Diffstat (limited to 'lldb/source/Core/Debugger.cpp')
| -rw-r--r-- | lldb/source/Core/Debugger.cpp | 138 |
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; } |
