[Lldb-commits] [lldb] [lldb] Emit diagnostics as "important" output (PR #137280)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Fri Apr 25 09:18:11 PDT 2025
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 <jonas at devlieghere.com>
Date: Thu, 24 Apr 2025 17:59:29 -0700
Subject: [PATCH 1/3] [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
>From 2c4b82359c21cd01c5b668c888b1d30d4f35cf6c Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Thu, 24 Apr 2025 19:36:05 -0700
Subject: [PATCH 2/3] Appease the formatter
---
.../Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py | 1 -
1 file changed, 1 deletion(-)
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 5f90830a34059..338e42f2bbbb7 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
@@ -235,7 +235,6 @@ def collect_important(self, timeout_secs, pattern=None):
"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.
>From a822059b49768ae2907e0266c32240d9e23f92bc Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Fri, 25 Apr 2025 09:17:56 -0700
Subject: [PATCH 3/3] Use unqualified eBroadcastBitError and
eBroadcastBitWarning
---
lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
index 56089fb08b2ea..7d8ac676ba935 100644
--- a/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/InitializeRequestHandler.cpp
@@ -118,9 +118,8 @@ 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);
+ dap.debugger.GetBroadcaster().AddListener(listener, eBroadcastBitError |
+ eBroadcastBitWarning);
bool done = false;
while (!done) {
if (listener.WaitForEvent(1, event)) {
More information about the lldb-commits
mailing list