https://github.com/JDevlieghere updated https://github.com/llvm/llvm-project/pull/137280
>From c2eab3f2f09fd771cbd8c18f141de1fa7664af49 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <jo...@devlieghere.com> Date: Thu, 24 Apr 2025 17:59:29 -0700 Subject: [PATCH] [lldb] Emit diagnostics as "important" output Handle diagnostics events from the debugger (i.e. asynchronous errors and warnings) in the lldb-dap event handler and emit them as "important" output. --- .../test/tools/lldb-dap/lldbdap_testcase.py | 13 ++++++++-- .../tools/lldb-dap/console/TestDAP_console.py | 17 +++++++++++++ .../API/tools/lldb-dap/console/minidump.yaml | 24 +++++++++++++++++++ lldb/tools/lldb-dap/DAP.cpp | 3 +++ lldb/tools/lldb-dap/DAP.h | 2 +- .../Handler/InitializeRequestHandler.cpp | 13 ++++++++++ lldb/tools/lldb-dap/LLDBUtils.cpp | 14 +++++++++++ lldb/tools/lldb-dap/LLDBUtils.h | 3 +++ 8 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 lldb/test/API/tools/lldb-dap/console/minidump.yaml diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py index b5b55b336d535..5f90830a34059 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py @@ -217,16 +217,25 @@ def get_stdout(self, timeout=0.0): def get_console(self, timeout=0.0): return self.dap_server.get_output("console", timeout=timeout) + def get_important(self, timeout=0.0): + return self.dap_server.get_output("important", timeout=timeout) + + def collect_stdout(self, timeout_secs, pattern=None): + return self.dap_server.collect_output( + "stdout", timeout_secs=timeout_secs, pattern=pattern + ) + def collect_console(self, timeout_secs, pattern=None): return self.dap_server.collect_output( "console", timeout_secs=timeout_secs, pattern=pattern ) - def collect_stdout(self, timeout_secs, pattern=None): + def collect_important(self, timeout_secs, pattern=None): return self.dap_server.collect_output( - "stdout", timeout_secs=timeout_secs, pattern=pattern + "important", timeout_secs=timeout_secs, pattern=pattern ) + def get_local_as_int(self, name, threadId=None): value = self.dap_server.get_local_variable_value(name, threadId=threadId) # 'value' may have the variable value and summary. diff --git a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py index 8bbab8d0991de..b07c4f871d73b 100644 --- a/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py +++ b/lldb/test/API/tools/lldb-dap/console/TestDAP_console.py @@ -164,3 +164,20 @@ def test_exit_status_message_ok(self): console_output, "Exit status does not contain message 'exited with status'", ) + + def test_diagnositcs(self): + program = self.getBuildArtifact("a.out") + self.build_and_launch(program) + + core = self.getBuildArtifact("minidump.core") + self.yaml2obj("minidump.yaml", core) + self.dap_server.request_evaluate( + f"target create --core {core}", context="repl" + ) + + output = self.get_important() + self.assertIn( + "warning: unable to retrieve process ID from minidump file", + output, + "diagnostic found in important output", + ) diff --git a/lldb/test/API/tools/lldb-dap/console/minidump.yaml b/lldb/test/API/tools/lldb-dap/console/minidump.yaml new file mode 100644 index 0000000000000..42f0a23702950 --- /dev/null +++ b/lldb/test/API/tools/lldb-dap/console/minidump.yaml @@ -0,0 +1,24 @@ +--- !minidump +Streams: + - Type: ThreadList + Threads: + - Thread Id: 0x00003E81 + Context: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000B0010000000000033000000000000000000000006020100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010A234EBFC7F000010A234EBFC7F00000000000000000000F09C34EBFC7F0000C0A91ABCE97F00000000000000000000A0163FBCE97F00004602000000000000921C40000000000030A434EBFC7F000000000000000000000000000000000000C61D4000000000007F0300000000000000000000000000000000000000000000801F0000FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF25252525252525252525252525252525000000000000000000000000000000000000000000000000000000000000000000FFFF00FFFFFFFFFFFFFF00FFFFFFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + Stack: + Start of Memory Range: 0x00007FFCEB34A000 + Content: '' + - Type: ModuleList + Modules: + - Base of Image: 0x0000000000400000 + Size of Image: 0x00017000 + Module Name: 'a.out' + CodeView Record: '' + - Type: SystemInfo + Processor Arch: AMD64 + Platform ID: Linux + CSD Version: 'Linux 3.13' + CPU: + Vendor ID: GenuineIntel + Version Info: 0x00000000 + Feature Info: 0x00000000 +... diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp index 134762711b89d..09f7e817707bc 100644 --- a/lldb/tools/lldb-dap/DAP.cpp +++ b/lldb/tools/lldb-dap/DAP.cpp @@ -342,6 +342,9 @@ void DAP::SendOutput(OutputType o, const llvm::StringRef output) { case OutputType::Console: category = "console"; break; + case OutputType::Important: + category = "important"; + break; case OutputType::Stdout: category = "stdout"; break; diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h index 727e5c00623e8..e8673705119e4 100644 --- a/lldb/tools/lldb-dap/DAP.h +++ b/lldb/tools/lldb-dap/DAP.h @@ -67,7 +67,7 @@ typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint> using AdapterFeature = protocol::AdapterFeature; using ClientFeature = protocol::ClientFeature; -enum class OutputType { Console, Stdout, Stderr, Telemetry }; +enum class OutputType { Console, Important, Stdout, Stderr, Telemetry }; /// Buffer size for handling output events. constexpr uint64_t OutputBufferSize = (1u << 12); diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp index b4250cd6becb3..56089fb08b2ea 100644 --- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp +++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp @@ -9,6 +9,7 @@ #include "DAP.h" #include "EventHelper.h" #include "JSONUtils.h" +#include "LLDBUtils.h" #include "Protocol/ProtocolRequests.h" #include "RequestHandler.h" #include "lldb/API/SBEvent.h" @@ -117,6 +118,9 @@ static void EventThreadFunction(DAP &dap) { lldb::SBEvent event; lldb::SBListener listener = dap.debugger.GetListener(); dap.broadcaster.AddListener(listener, eBroadcastBitStopEventThread); + dap.debugger.GetBroadcaster().AddListener( + listener, lldb::SBDebugger::eBroadcastBitError | + lldb::SBDebugger::eBroadcastBitWarning); bool done = false; while (!done) { if (listener.WaitForEvent(1, event)) { @@ -222,6 +226,15 @@ static void EventThreadFunction(DAP &dap) { dap.SendJSON(llvm::json::Value(std::move(bp_event))); } } + } else if (event_mask & eBroadcastBitError || + event_mask & eBroadcastBitWarning) { + SBStructuredData data = SBDebugger::GetDiagnosticFromEvent(event); + if (!data.IsValid()) + continue; + std::string type = GetStringValue(data.GetValueForKey("type")); + std::string message = GetStringValue(data.GetValueForKey("message")); + dap.SendOutput(OutputType::Important, + llvm::formatv("{0}: {1}", type, message).str()); } else if (event.BroadcasterMatchesRef(dap.broadcaster)) { if (event_mask & eBroadcastBitStopEventThread) { done = true; diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp index a27beff0b030d..0b3d416ecbe3d 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.cpp +++ b/lldb/tools/lldb-dap/LLDBUtils.cpp @@ -10,6 +10,7 @@ #include "DAP.h" #include "JSONUtils.h" #include "lldb/API/SBStringList.h" +#include "lldb/API/SBStructuredData.h" #include <mutex> @@ -172,4 +173,17 @@ llvm::Error ToError(const lldb::SBError &error) { error.GetCString()); } +std::string GetStringValue(const lldb::SBStructuredData &data) { + if (!data.IsValid()) + return ""; + + const size_t str_length = data.GetStringValue(nullptr, 0); + if (!str_length) + return ""; + + std::string str(str_length, 0); + data.GetStringValue(&str[0], str_length + 1); + return str; +} + } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h index 2c57847303cb3..7d51427123c0f 100644 --- a/lldb/tools/lldb-dap/LLDBUtils.h +++ b/lldb/tools/lldb-dap/LLDBUtils.h @@ -159,6 +159,9 @@ GetEnvironmentFromArguments(const llvm::json::Object &arguments); /// Take ownership of the stored error. llvm::Error ToError(const lldb::SBError &error); +/// Provides the string value if this data structure is a string type. +std::string GetStringValue(const lldb::SBStructuredData &data); + } // namespace lldb_dap #endif _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits