[Lldb-commits] [lldb] [lldb-dap] Return raw stop info from exceptionInfo (PR #231760)
via lldb-commits
lldb-commits at lists.llvm.org
Tue Oct 13 22:56:17 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Jonas Devlieghere (JDevlieghere)
<details>
<summary>Changes</summary>
lldb-dap folds the thread's extended stop info and the process's extended crash information into the exceptionInfo description as formatted text. Clients that want interpret these themselves currently have to parse them back out.
Return both as raw JSON in two new lldb-dap extension fields, `$__lldb_stopReasonExtendedInfo` and `$__lldb_extendedCrashInformation`.
rdar://188761988
---
Full diff: https://github.com/llvm/llvm-project/pull/231760.diff
7 Files Affected:
- (modified) lldb/packages/Python/lldbsuite/test/tools/lldb_dap/types.py (+6)
- (modified) lldb/test/API/tools/lldb-dap/exception/asan/TestDAP_asan.py (+6)
- (modified) lldb/test/API/tools/lldb-dap/exception/ubsan/TestDAP_ubsan.py (+7)
- (modified) lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp (+34)
- (modified) lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp (+6)
- (modified) lldb/tools/lldb-dap/Protocol/ProtocolRequests.h (+13)
- (modified) lldb/unittests/DAP/ProtocolRequestsTest.cpp (+9)
``````````diff
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/types.py b/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/types.py
index 24b33ae938161..310a9f01131d5 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/types.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb_dap/types.py
@@ -1731,6 +1731,12 @@ class Body:
breakMode: ExceptionBreakMode
description: Optional[str] = None
details: Optional[ExceptionDetails] = None
+ lldb_stop_reason_extended_info: Optional[Dict[str, Any]] = field(
+ metadata={"alias": "$__lldb_stopReasonExtendedInfo"}, default=None
+ )
+ lldb_extended_crash_information: Optional[Dict[str, Any]] = field(
+ metadata={"alias": "$__lldb_extendedCrashInformation"}, default=None
+ )
body: Body
diff --git a/lldb/test/API/tools/lldb-dap/exception/asan/TestDAP_asan.py b/lldb/test/API/tools/lldb-dap/exception/asan/TestDAP_asan.py
index 395cd68db25fe..24f0907068516 100644
--- a/lldb/test/API/tools/lldb-dap/exception/asan/TestDAP_asan.py
+++ b/lldb/test/API/tools/lldb-dap/exception/asan/TestDAP_asan.py
@@ -28,3 +28,9 @@ def test_asan(self):
description = self.expect_not_none(exception_info.description)
self.assertRegex(description, r"fatal_error: heap-use-after-free")
self.assertEqual(exception_info.exceptionId, "runtime-instrumentation")
+
+ stop_info = self.expect_not_none(
+ exception_info.lldb_stop_reason_extended_info
+ )
+ self.assertEqual(stop_info["instrumentation_class"], "AddressSanitizer")
+ self.assertEqual(stop_info["description"], "heap-use-after-free")
diff --git a/lldb/test/API/tools/lldb-dap/exception/ubsan/TestDAP_ubsan.py b/lldb/test/API/tools/lldb-dap/exception/ubsan/TestDAP_ubsan.py
index 23ba0747311e9..4e5cfe836e52a 100644
--- a/lldb/test/API/tools/lldb-dap/exception/ubsan/TestDAP_ubsan.py
+++ b/lldb/test/API/tools/lldb-dap/exception/ubsan/TestDAP_ubsan.py
@@ -30,6 +30,13 @@ def test_ubsan(self):
self.assertRegex(description, r"Out of bounds index")
self.assertEqual(exception_info.exceptionId, "runtime-instrumentation")
+ stop_info = self.expect_not_none(
+ exception_info.lldb_stop_reason_extended_info
+ )
+ self.assertEqual(
+ stop_info["instrumentation_class"], "UndefinedBehaviorSanitizer"
+ )
+
# FIXME: Check on non macOS platform the stop information location heuristic
# may be wrong. enable when we have updated Ubsan stopInfo heuristic.
if self.platformIsDarwin():
diff --git a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
index f15d35f3954da..bea427519126a 100644
--- a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
@@ -271,6 +271,34 @@ static std::string FormatCrashReport(lldb::SBThread &thread) {
return report;
}
+static std::optional<json::Value> ParseJSON(DAP &dap, lldb::SBStream &stream) {
+ Expected<json::Value> value =
+ json::parse({stream.GetData(), stream.GetSize()});
+ if (!value) {
+ DAP_LOG_ERROR(dap.log, value.takeError(), "invalid JSON: {0}");
+ return std::nullopt;
+ }
+ return std::move(*value);
+}
+
+static std::optional<json::Value> GetExtendedStopInfo(DAP &dap,
+ lldb::SBThread &thread) {
+ lldb::SBStream stream;
+ if (!thread.GetStopReasonExtendedInfoAsJSON(stream))
+ return std::nullopt;
+ return ParseJSON(dap, stream);
+}
+
+static std::optional<json::Value>
+GetExtendedCrashInformation(DAP &dap, lldb::SBThread &thread) {
+ lldb::SBStructuredData crash_info =
+ thread.GetProcess().GetExtendedCrashInformation();
+ lldb::SBStream stream;
+ if (!crash_info || crash_info.GetAsJSON(stream).Fail())
+ return std::nullopt;
+ return ParseJSON(dap, stream);
+}
+
static std::string FormatStackTrace(lldb::SBThread &thread) {
std::string stack_trace;
raw_string_ostream OS(stack_trace);
@@ -348,6 +376,12 @@ ExceptionInfoRequestHandler::Run(const ExceptionInfoArguments &args) const {
!crash_report.empty())
body.description += formatv("\n\n{0}", crash_report);
+ // Clients that interpret these themselves shouldn't have to parse them back
+ // out of the description.
+ body.lldbExtStopReasonExtendedInfo = GetExtendedStopInfo(dap, thread);
+ body.lldbExtExtendedCrashInformation =
+ GetExtendedCrashInformation(dap, thread);
+
lldb::SBProcess process = thread.GetProcess();
for (uint32_t idx = 0; idx < lldb::eNumInstrumentationRuntimeTypes; idx++) {
auto type = static_cast<lldb::InstrumentationRuntimeType>(idx);
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index c952c17512952..6a7f4e57b243a 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -695,6 +695,12 @@ json::Value toJSON(const ExceptionInfoResponseBody &ERB) {
result.insert({"description", ERB.description});
if (ERB.details.has_value())
result.insert({"details", *ERB.details});
+ if (ERB.lldbExtStopReasonExtendedInfo)
+ result.insert(
+ {"$__lldb_stopReasonExtendedInfo", *ERB.lldbExtStopReasonExtendedInfo});
+ if (ERB.lldbExtExtendedCrashInformation)
+ result.insert({"$__lldb_extendedCrashInformation",
+ *ERB.lldbExtExtendedCrashInformation});
return result;
}
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index d8cc9d4cad223..169052183b110 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -1071,6 +1071,19 @@ struct ExceptionInfoResponseBody {
/// Detailed information about the exception.
std::optional<ExceptionDetails> details;
+
+ /// lldb-dap Extensions
+ /// @{
+
+ /// The thread's stop reason extended info, as reported by
+ /// `SBThread::GetStopReasonExtendedInfoAsJSON`.
+ std::optional<llvm::json::Value> lldbExtStopReasonExtendedInfo;
+
+ /// The process's extended crash information, as reported by
+ /// `SBProcess::GetExtendedCrashInformation`.
+ std::optional<llvm::json::Value> lldbExtExtendedCrashInformation;
+
+ /// @}
};
llvm::json::Value toJSON(const ExceptionInfoResponseBody &);
diff --git a/lldb/unittests/DAP/ProtocolRequestsTest.cpp b/lldb/unittests/DAP/ProtocolRequestsTest.cpp
index af0d69f3a9ac4..f0a71d25f21dd 100644
--- a/lldb/unittests/DAP/ProtocolRequestsTest.cpp
+++ b/lldb/unittests/DAP/ProtocolRequestsTest.cpp
@@ -55,6 +55,9 @@ TEST(ProtocolRequestsTest, ExceptionInfoResponseBody) {
body.breakMode = eExceptionBreakModeNever;
body.details = ExceptionDetails{};
body.details->message = "some message";
+ body.lldbExtStopReasonExtendedInfo =
+ json::Object{{"instrumentation_class", "AddressSanitizer"}};
+ body.lldbExtExtendedCrashInformation = json::Object{{"crash-info", "abort"}};
Expected<json::Value> expected_opt = parse(
R"({
@@ -63,6 +66,12 @@ TEST(ProtocolRequestsTest, ExceptionInfoResponseBody) {
"breakMode": "never",
"details": {
"message": "some message"
+ },
+ "$__lldb_stopReasonExtendedInfo": {
+ "instrumentation_class": "AddressSanitizer"
+ },
+ "$__lldb_extendedCrashInformation": {
+ "crash-info": "abort"
}
})");
``````````
</details>
https://github.com/llvm/llvm-project/pull/231760
More information about the lldb-commits
mailing list