https://github.com/ashgti updated 
https://github.com/llvm/llvm-project/pull/176465

>From 0b50dabc60648c3211787d534dd14cea5279f9ac Mon Sep 17 00:00:00 2001
From: John Harrison <[email protected]>
Date: Fri, 16 Jan 2026 11:31:17 -0800
Subject: [PATCH 1/4] [lldb-dap] Adding more details to 'exceptionInfo'.

---
 .../test/tools/lldb-dap/lldbdap_testcase.py   | 48 ++++++----
 .../TestDAP_setExceptionBreakpoints.py        |  8 +-
 .../lldb-dap/exception/TestDAP_exception.py   |  2 +-
 .../exception/cpp/TestDAP_exception_cpp.py    |  5 +-
 .../exception/objc/TestDAP_exception_objc.py  | 10 +--
 .../exception/runtime-instruments/Makefile    |  4 +
 .../TestDAP_runtime_instruments.py            | 25 ++++++
 .../exception/runtime-instruments/categories  |  1 +
 .../exception/runtime-instruments/main.c      |  5 ++
 .../Handler/ExceptionInfoRequestHandler.cpp   | 90 +++++++++++++------
 10 files changed, 144 insertions(+), 54 deletions(-)
 create mode 100644 
lldb/test/API/tools/lldb-dap/exception/runtime-instruments/Makefile
 create mode 100644 
lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
 create mode 100644 
lldb/test/API/tools/lldb-dap/exception/runtime-instruments/categories
 create mode 100644 
lldb/test/API/tools/lldb-dap/exception/runtime-instruments/main.c

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 e4a3e1c786ffed..b2cac4dfb0e5bf 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
@@ -208,25 +208,40 @@ def verify_all_breakpoints_hit(self, breakpoint_ids):
                     return
         self.assertTrue(False, f"breakpoints not hit, 
stopped_events={stopped_events}")
 
-    def verify_stop_exception_info(self, expected_description):
+    def verify_stop_exception_info(
+        self, expected_description: str, expected_text: Optional[str] = None
+    ) -> None:
         """Wait for the process we are debugging to stop, and verify the stop
         reason is 'exception' and that the description matches
         'expected_description'
         """
         stopped_events = self.dap_server.wait_for_stopped()
+        self.assertIsNotNone(stopped_events, "No stopped events detected")
         for stopped_event in stopped_events:
-            if "body" in stopped_event:
-                body = stopped_event["body"]
-                if "reason" not in body:
-                    continue
-                if body["reason"] != "exception":
-                    continue
-                if "description" not in body:
-                    continue
-                description = body["description"]
-                if expected_description == description:
-                    return True
-        return False
+            if (
+                "body" not in stopped_event
+                or stopped_event["body"]["reason"] != "exception"
+            ):
+                continue
+            self.assertIn(
+                "description",
+                stopped_event["body"],
+                f"stopped event missing description {stopped_event}",
+            )
+            description = stopped_event["body"]["description"]
+            self.assertRegex(
+                description,
+                expected_description,
+                f"for 'stopped' event {stopped_event!r}",
+            )
+            if expected_text:
+                self.assertRegex(
+                    stopped_event["body"]["text"],
+                    expected_text,
+                    f"for stopped event {stopped_event!r}",
+                )
+            return
+        self.fail(f"No valid stop exception info detected in {stopped_events}")
 
     def verify_stop_on_entry(self) -> None:
         """Waits for the process to be stopped and then verifies at least one
@@ -437,12 +452,9 @@ def continue_to_breakpoints(self, breakpoint_ids):
         self.do_continue()
         self.verify_breakpoint_hit(breakpoint_ids)
 
-    def continue_to_exception_breakpoint(self, filter_label):
+    def continue_to_exception_breakpoint(self, description, text=None):
         self.do_continue()
-        self.assertTrue(
-            self.verify_stop_exception_info(filter_label),
-            'verify we got "%s"' % (filter_label),
-        )
+        self.verify_stop_exception_info(description, text)
 
     def continue_to_exit(self, exitCode=0):
         self.do_continue()
diff --git 
a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
index 4ca733a9a59cac..684726c927bc11 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
@@ -35,5 +35,9 @@ def test_functionality(self):
         if response:
             self.assertTrue(response["success"])
 
-        self.continue_to_exception_breakpoint("C++ Throw")
-        self.continue_to_exception_breakpoint("C++ Catch")
+        self.continue_to_exception_breakpoint(
+            r"breakpoint \d+\.\d+", text=r"C\+\+ Throw"
+        )
+        self.continue_to_exception_breakpoint(
+            r"breakpoint \d+\.\d+", text=r"C\+\+ Catch"
+        )
diff --git a/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py 
b/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py
index f044bcae418921..b92c3290ceb4cb 100644
--- a/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py
+++ b/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py
@@ -18,7 +18,7 @@ def test_stopped_description(self):
         self.build_and_launch(program)
         self.do_continue()
 
-        self.assertTrue(self.verify_stop_exception_info("signal SIGABRT"))
+        self.verify_stop_exception_info("signal SIGABRT")
         exceptionInfo = self.get_exceptionInfo()
         self.assertEqual(exceptionInfo["breakMode"], "always")
         self.assertEqual(exceptionInfo["description"], "signal SIGABRT")
diff --git 
a/lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py 
b/lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py
index 6471e2b87251a7..4729cbef00c113 100644
--- a/lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py
+++ b/lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py
@@ -2,7 +2,6 @@
 Test exception behavior in DAP with c++ throw.
 """
 
-
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 import lldbdap_testcase
@@ -18,9 +17,9 @@ def test_stopped_description(self):
         program = self.getBuildArtifact("a.out")
         self.build_and_launch(program)
         self.dap_server.request_continue()
-        self.assertTrue(self.verify_stop_exception_info("signal SIGABRT"))
+        self.verify_stop_exception_info("signal SIGABRT")
         exceptionInfo = self.get_exceptionInfo()
         self.assertEqual(exceptionInfo["breakMode"], "always")
-        self.assertEqual(exceptionInfo["description"], "signal SIGABRT")
+        self.assertIn("signal SIGABRT", exceptionInfo["description"])
         self.assertEqual(exceptionInfo["exceptionId"], "signal")
         self.assertIsNotNone(exceptionInfo["details"])
diff --git 
a/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py 
b/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
index ddedf7a6de8c6c..40233af4b2bd6a 100644
--- a/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
+++ b/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
@@ -16,10 +16,10 @@ def test_stopped_description(self):
         program = self.getBuildArtifact("a.out")
         self.build_and_launch(program)
         self.dap_server.request_continue()
-        self.assertTrue(self.verify_stop_exception_info("signal SIGABRT"))
+        self.verify_stop_exception_info("signal SIGABRT")
         exception_info = self.get_exceptionInfo()
         self.assertEqual(exception_info["breakMode"], "always")
-        self.assertEqual(exception_info["description"], "signal SIGABRT")
+        self.assertIn("signal SIGABRT", exception_info["description"])
         self.assertEqual(exception_info["exceptionId"], "signal")
         exception_details = exception_info["details"]
         self.assertRegex(exception_details["message"], "SomeReason")
@@ -44,7 +44,7 @@ def test_break_on_throw_and_catch(self):
         if response:
             self.assertTrue(response["success"])
 
-        self.continue_to_exception_breakpoint("Objective-C Throw")
+        self.continue_to_exception_breakpoint("hit Objective-C exception")
 
         # FIXME: Catching objc exceptions do not appear to be working.
         # Xcode appears to set a breakpoint on '__cxa_begin_catch' for objc
@@ -54,10 +54,10 @@ def test_break_on_throw_and_catch(self):
 
         self.do_continue()
 
-        self.assertTrue(self.verify_stop_exception_info("signal SIGABRT"))
+        self.verify_stop_exception_info("signal SIGABRT")
         exception_info = self.get_exceptionInfo()
         self.assertEqual(exception_info["breakMode"], "always")
-        self.assertEqual(exception_info["description"], "signal SIGABRT")
+        self.assertIn("signal SIGABRT", exception_info["description"])
         self.assertEqual(exception_info["exceptionId"], "signal")
         exception_details = exception_info["details"]
         self.assertRegex(exception_details["message"], "SomeReason")
diff --git 
a/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/Makefile 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/Makefile
new file mode 100644
index 00000000000000..b27db90a40de2f
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/Makefile
@@ -0,0 +1,4 @@
+C_SOURCES := main.c
+CFLAGS_EXTRAS := -fsanitize=undefined -g
+
+include Makefile.rules
diff --git 
a/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
new file mode 100644
index 00000000000000..caff7dd1bedcd1
--- /dev/null
+++ 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
@@ -0,0 +1,25 @@
+"""
+Test that we stop at runtime instrumentation locations.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbdap_testcase
+
+
+class TestDAP_runtime_instruments(lldbdap_testcase.DAPTestCaseBase):
+    @skipUnlessUndefinedBehaviorSanitizer
+    def test_ubsan(self):
+        """
+        Test that we stop at ubsan.
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        self.do_continue()
+
+        self.verify_stop_exception_info("Out of bounds index")
+        exceptionInfo = self.get_exceptionInfo()
+        self.assertEqual(exceptionInfo["breakMode"], "always")
+        self.assertEqual("Out of bounds index", exceptionInfo["description"])
+        self.assertEqual(exceptionInfo["exceptionId"], 
"runtime-instrumentation")
+        self.assertIn("main.c", exceptionInfo["details"]["stackTrace"])
diff --git 
a/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/categories 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/categories
new file mode 100644
index 00000000000000..c756cb12419455
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/categories
@@ -0,0 +1 @@
+instrumentation-runtime
diff --git a/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/main.c 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/main.c
new file mode 100644
index 00000000000000..9434b8e2d75833
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/main.c
@@ -0,0 +1,5 @@
+int main(int argc, char const *argv[]) {
+  int data[4] = {0};
+  int *p = data + 5; // ubsan
+  return *p;
+}
diff --git a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
index ddf55e6fb382d0..c76fc83fa8cbee 100644
--- a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
@@ -8,15 +8,30 @@
 
 #include "DAP.h"
 #include "DAPError.h"
+#include "DAPLog.h"
 #include "Protocol/ProtocolRequests.h"
 #include "Protocol/ProtocolTypes.h"
 #include "RequestHandler.h"
 #include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBThreadCollection.h"
+#include "lldb/lldb-enumerations.h"
+#include <utility>
 
 using namespace lldb_dap::protocol;
 
 namespace lldb_dap {
 
+static std::string ThreadSummary(lldb::SBThread &thread) {
+  lldb::SBStream stream;
+  thread.GetDescription(stream);
+  for (uint32_t idx = 0; idx < thread.GetNumFrames(); idx++) {
+    lldb::SBFrame frame = thread.GetFrameAtIndex(idx);
+    frame.GetDescription(stream);
+  }
+  return {stream.GetData(), stream.GetSize()};
+}
+
 /// Retrieves the details of the exception that caused this event to be raised.
 ///
 /// Clients should only call this request if the corresponding capability
@@ -29,53 +44,78 @@ ExceptionInfoRequestHandler::Run(const 
ExceptionInfoArguments &args) const {
     return llvm::make_error<DAPError>(
         llvm::formatv("Invalid thread id: {}", args.threadId).str());
 
-  ExceptionInfoResponseBody response;
-  response.breakMode = eExceptionBreakModeAlways;
+  ExceptionInfoResponseBody body;
+  body.breakMode = eExceptionBreakModeAlways;
   const lldb::StopReason stop_reason = thread.GetStopReason();
   switch (stop_reason) {
+  case lldb::eStopReasonInstrumentation:
+    body.exceptionId = "runtime-instrumentation";
+    break;
   case lldb::eStopReasonSignal:
-    response.exceptionId = "signal";
+    body.exceptionId = "signal";
     break;
   case lldb::eStopReasonBreakpoint: {
     const ExceptionBreakpoint *exc_bp =
         dap.GetExceptionBPFromStopReason(thread);
     if (exc_bp) {
-      response.exceptionId = exc_bp->GetFilter();
-      response.description = exc_bp->GetLabel();
+      body.exceptionId = exc_bp->GetFilter();
+      body.description = exc_bp->GetLabel().str() + "\n";
     } else {
-      response.exceptionId = "exception";
+      body.exceptionId = "exception";
     }
   } break;
   default:
-    response.exceptionId = "exception";
+    body.exceptionId = "exception";
   }
 
   lldb::SBStream stream;
-  if (response.description.empty()) {
-    if (thread.GetStopDescription(stream)) {
-      response.description = {stream.GetData(), stream.GetSize()};
-    }
-  }
+  if (thread.GetStopDescription(stream))
+    body.description += {stream.GetData(), stream.GetSize()};
 
   if (lldb::SBValue exception = thread.GetCurrentException()) {
+    body.details = ExceptionDetails{};
+    if (const char *name = exception.GetName())
+      body.details->evaluateName = name;
+    if (const char *typeName = exception.GetDisplayTypeName())
+      body.details->typeName = typeName;
+
     stream.Clear();
-    response.details = ExceptionDetails{};
-    if (exception.GetDescription(stream)) {
-      response.details->message = {stream.GetData(), stream.GetSize()};
-    }
+    if (exception.GetDescription(stream))
+      body.details->message = {stream.GetData(), stream.GetSize()};
 
     if (lldb::SBThread exception_backtrace =
-            thread.GetCurrentExceptionBacktrace()) {
-      stream.Clear();
-      exception_backtrace.GetDescription(stream);
+            thread.GetCurrentExceptionBacktrace())
+      body.details->stackTrace = ThreadSummary(exception_backtrace);
+  }
 
-      for (uint32_t idx = 0; idx < exception_backtrace.GetNumFrames(); idx++) {
-        lldb::SBFrame frame = exception_backtrace.GetFrameAtIndex(idx);
-        frame.GetDescription(stream);
-      }
-      response.details->stackTrace = {stream.GetData(), stream.GetSize()};
+  lldb::SBStructuredData crash_info =
+      dap.target.GetProcess().GetExtendedCrashInformation();
+  stream.Clear();
+  if (crash_info.IsValid() && crash_info.GetDescription(stream))
+    body.description += "\n\nExtended Crash Information:\n" +
+                        std::string(stream.GetData(), stream.GetSize());
+
+  for (uint32_t idx = 0; idx < lldb::eNumInstrumentationRuntimeTypes; idx++) {
+    lldb::InstrumentationRuntimeType type =
+        static_cast<lldb::InstrumentationRuntimeType>(idx);
+    if (!dap.target.GetProcess().IsInstrumentationRuntimePresent(type))
+      continue;
+    lldb::SBThreadCollection threads =
+        thread.GetStopReasonExtendedBacktraces(type);
+    for (uint32_t tidx = 0; tidx < threads.GetSize(); tidx++) {
+      auto thread = threads.GetThreadAtIndex(tidx);
+      if (!thread)
+        continue;
+      ExceptionDetails details;
+      details.stackTrace = ThreadSummary(thread);
+      if (!body.details)
+        body.details = std::move(details);
+      else
+        body.details->innerException.emplace_back(std::move(details));
     }
   }
-  return response;
+
+  return body;
 }
+
 } // namespace lldb_dap

>From 4b209449608a5e394af5ee603c81f3539f756e8d Mon Sep 17 00:00:00 2001
From: John Harrison <[email protected]>
Date: Fri, 16 Jan 2026 11:53:39 -0800
Subject: [PATCH 2/4] Fixing tests after splitting up the PR.

---
 .../breakpoint/TestDAP_setExceptionBreakpoints.py         | 8 ++------
 .../lldb-dap/exception/objc/TestDAP_exception_objc.py     | 2 +-
 2 files changed, 3 insertions(+), 7 deletions(-)

diff --git 
a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
index 684726c927bc11..5ed7e13fd0b447 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
@@ -35,9 +35,5 @@ def test_functionality(self):
         if response:
             self.assertTrue(response["success"])
 
-        self.continue_to_exception_breakpoint(
-            r"breakpoint \d+\.\d+", text=r"C\+\+ Throw"
-        )
-        self.continue_to_exception_breakpoint(
-            r"breakpoint \d+\.\d+", text=r"C\+\+ Catch"
-        )
+        self.continue_to_exception_breakpoint(r"C\+\+ Throw")
+        self.continue_to_exception_breakpoint(r"C\+\+ Catch")
diff --git 
a/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py 
b/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
index 40233af4b2bd6a..694cadb6ed2fed 100644
--- a/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
+++ b/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
@@ -44,7 +44,7 @@ def test_break_on_throw_and_catch(self):
         if response:
             self.assertTrue(response["success"])
 
-        self.continue_to_exception_breakpoint("hit Objective-C exception")
+        self.continue_to_exception_breakpoint("Objective-C Throw")
 
         # FIXME: Catching objc exceptions do not appear to be working.
         # Xcode appears to set a breakpoint on '__cxa_begin_catch' for objc

>From 967c61afb52495e34e484eab4ae45bf0f82d1c40 Mon Sep 17 00:00:00 2001
From: John Harrison <[email protected]>
Date: Tue, 20 Jan 2026 14:05:04 -0800
Subject: [PATCH 3/4] Using a variable to hold the SBProcess.

---
 .../lldb-dap/Handler/ExceptionInfoRequestHandler.cpp   | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
index c76fc83fa8cbee..f4168ade754482 100644
--- a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
@@ -88,8 +88,11 @@ ExceptionInfoRequestHandler::Run(const 
ExceptionInfoArguments &args) const {
       body.details->stackTrace = ThreadSummary(exception_backtrace);
   }
 
-  lldb::SBStructuredData crash_info =
-      dap.target.GetProcess().GetExtendedCrashInformation();
+  lldb::SBProcess process = dap.target.GetProcess();
+  if (!process)
+    return body;
+
+  lldb::SBStructuredData crash_info = process.GetExtendedCrashInformation();
   stream.Clear();
   if (crash_info.IsValid() && crash_info.GetDescription(stream))
     body.description += "\n\nExtended Crash Information:\n" +
@@ -98,8 +101,9 @@ ExceptionInfoRequestHandler::Run(const 
ExceptionInfoArguments &args) const {
   for (uint32_t idx = 0; idx < lldb::eNumInstrumentationRuntimeTypes; idx++) {
     lldb::InstrumentationRuntimeType type =
         static_cast<lldb::InstrumentationRuntimeType>(idx);
-    if (!dap.target.GetProcess().IsInstrumentationRuntimePresent(type))
+    if (!process.IsInstrumentationRuntimePresent(type))
       continue;
+
     lldb::SBThreadCollection threads =
         thread.GetStopReasonExtendedBacktraces(type);
     for (uint32_t tidx = 0; tidx < threads.GetSize(); tidx++) {

>From 48886ce8ebc79af47e446e388d925f6cc34359c6 Mon Sep 17 00:00:00 2001
From: John Harrison <[email protected]>
Date: Wed, 21 Jan 2026 15:53:57 -0800
Subject: [PATCH 4/4] Improving formatting by parsing extended stack trace
 json.

---
 .../TestDAP_runtime_instruments.py            |  2 +-
 .../Handler/ExceptionInfoRequestHandler.cpp   | 92 +++++++++++++++++--
 lldb/tools/lldb-dap/JSONUtils.cpp             |  2 +-
 3 files changed, 88 insertions(+), 8 deletions(-)

diff --git 
a/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
index caff7dd1bedcd1..3fa7aca91a926c 100644
--- 
a/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
+++ 
b/lldb/test/API/tools/lldb-dap/exception/runtime-instruments/TestDAP_runtime_instruments.py
@@ -20,6 +20,6 @@ def test_ubsan(self):
         self.verify_stop_exception_info("Out of bounds index")
         exceptionInfo = self.get_exceptionInfo()
         self.assertEqual(exceptionInfo["breakMode"], "always")
-        self.assertEqual("Out of bounds index", exceptionInfo["description"])
+        self.assertRegex(exceptionInfo["description"], r"Out of bounds index")
         self.assertEqual(exceptionInfo["exceptionId"], 
"runtime-instrumentation")
         self.assertIn("main.c", exceptionInfo["details"]["stackTrace"])
diff --git a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
index f4168ade754482..5ebe62d7d389c6 100644
--- a/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/ExceptionInfoRequestHandler.cpp
@@ -8,14 +8,18 @@
 
 #include "DAP.h"
 #include "DAPError.h"
-#include "DAPLog.h"
 #include "Protocol/ProtocolRequests.h"
 #include "Protocol/ProtocolTypes.h"
 #include "RequestHandler.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBThreadCollection.h"
+#include "lldb/lldb-defines.h"
 #include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include <string>
 #include <utility>
 
 using namespace lldb_dap::protocol;
@@ -32,19 +36,56 @@ static std::string ThreadSummary(lldb::SBThread &thread) {
   return {stream.GetData(), stream.GetSize()};
 }
 
+struct RuntimeInstrumentReport {
+  std::string description;
+  std::string instrument;
+  std::string summary;
+
+  std::string filename;
+  uint32_t column = LLDB_INVALID_COLUMN_NUMBER;
+  uint32_t line = LLDB_INVALID_LINE_NUMBER;
+
+  // keys found on UBSan
+  lldb::addr_t memory = LLDB_INVALID_ADDRESS;
+  lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+  std::vector<lldb::user_id_t> trace;
+
+  // keys found on MainThreadChecker
+  std::string api_name;
+  std::string class_name;
+  std::string selector;
+
+  // FIXME: TSan, ASan, BoundsSafety
+};
+
+static bool fromJSON(const llvm::json::Value &Params,
+                     RuntimeInstrumentReport &RIR, llvm::json::Path Path) {
+  llvm::json::ObjectMapper O(Params, Path);
+  return O && O.mapOptional("description", RIR.description) &&
+         O.mapOptional("instrumentation_class", RIR.instrument) &&
+         O.mapOptional("summary", RIR.summary) &&
+         O.mapOptional("filename", RIR.filename) &&
+         O.mapOptional("col", RIR.column) && O.mapOptional("line", RIR.line) &&
+         O.mapOptional("memory", RIR.memory) && O.mapOptional("tid", RIR.tid) 
&&
+         O.mapOptional("trace", RIR.trace) &&
+         O.mapOptional("api_name", RIR.api_name) &&
+         O.mapOptional("class_name", RIR.class_name) &&
+         O.mapOptional("selector", RIR.selector);
+}
+
 /// Retrieves the details of the exception that caused this event to be raised.
 ///
 /// Clients should only call this request if the corresponding capability
 /// `supportsExceptionInfoRequest` is true.
 llvm::Expected<ExceptionInfoResponseBody>
 ExceptionInfoRequestHandler::Run(const ExceptionInfoArguments &args) const {
-
   lldb::SBThread thread = dap.GetLLDBThread(args.threadId);
   if (!thread.IsValid())
     return llvm::make_error<DAPError>(
         llvm::formatv("Invalid thread id: {}", args.threadId).str());
 
   ExceptionInfoResponseBody body;
+  llvm::raw_string_ostream OS(body.description);
   body.breakMode = eExceptionBreakModeAlways;
   const lldb::StopReason stop_reason = thread.GetStopReason();
   switch (stop_reason) {
@@ -59,7 +100,7 @@ ExceptionInfoRequestHandler::Run(const 
ExceptionInfoArguments &args) const {
         dap.GetExceptionBPFromStopReason(thread);
     if (exc_bp) {
       body.exceptionId = exc_bp->GetFilter();
-      body.description = exc_bp->GetLabel().str() + "\n";
+      OS << exc_bp->GetLabel().str();
     } else {
       body.exceptionId = "exception";
     }
@@ -70,7 +111,46 @@ ExceptionInfoRequestHandler::Run(const 
ExceptionInfoArguments &args) const {
 
   lldb::SBStream stream;
   if (thread.GetStopDescription(stream))
-    body.description += {stream.GetData(), stream.GetSize()};
+    OS << std::string{stream.GetData(), stream.GetSize()};
+
+  stream.Clear();
+  if (thread.GetStopReasonExtendedInfoAsJSON(stream)) {
+    OS << "\n";
+
+    llvm::Expected<RuntimeInstrumentReport> report =
+        llvm::json::parse<RuntimeInstrumentReport>(
+            {stream.GetData(), stream.GetSize()});
+    // If we failed to parse the extended stop reason info, attach it
+    // unmodified.
+    if (!report) {
+      llvm::consumeError(report.takeError());
+      OS << std::string(stream.GetData(), stream.GetSize());
+    } else {
+      if (!report->filename.empty()) {
+        OS << report->filename;
+        if (report->line != LLDB_INVALID_LINE_NUMBER) {
+          OS << ":" << report->line;
+          if (report->column != LLDB_INVALID_COLUMN_NUMBER)
+            OS << ":" << report->column;
+        }
+        OS << " ";
+      }
+
+      OS << report->instrument;
+      if (!report->description.empty())
+        OS << ": " << report->description;
+      OS << "\n";
+      if (!report->summary.empty())
+        OS << report->summary << "\n";
+
+      if (!report->api_name.empty())
+        OS << "API Name: " << report->api_name << "\n";
+      if (!report->class_name.empty())
+        OS << "Class Name: " << report->class_name << "\n";
+      if (!report->selector.empty())
+        OS << "Selector: " << report->selector << "\n";
+    }
+  }
 
   if (lldb::SBValue exception = thread.GetCurrentException()) {
     body.details = ExceptionDetails{};
@@ -95,8 +175,8 @@ ExceptionInfoRequestHandler::Run(const 
ExceptionInfoArguments &args) const {
   lldb::SBStructuredData crash_info = process.GetExtendedCrashInformation();
   stream.Clear();
   if (crash_info.IsValid() && crash_info.GetDescription(stream))
-    body.description += "\n\nExtended Crash Information:\n" +
-                        std::string(stream.GetData(), stream.GetSize());
+    OS << "\nExtended Crash Information:\n" +
+              std::string(stream.GetData(), stream.GetSize());
 
   for (uint32_t idx = 0; idx < lldb::eNumInstrumentationRuntimeTypes; idx++) {
     lldb::InstrumentationRuntimeType type =
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 5c33c6aa591a6a..f41f3e030e6a06 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -532,7 +532,7 @@ llvm::json::Value CreateThreadStopped(DAP &dap, 
lldb::SBThread &thread,
                       llvm::formatv("data breakpoint {0}", bp_id).str());
   } break;
   case lldb::eStopReasonInstrumentation:
-    body.try_emplace("reason", "breakpoint");
+    body.try_emplace("reason", "exception");
     break;
   case lldb::eStopReasonProcessorTrace:
     body.try_emplace("reason", "processor trace");

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to