[Lldb-commits] [lldb] [lldb-dap] Improve `stackTrace` and `exceptionInfo` DAP request handlers (PR #105905)

via lldb-commits lldb-commits at lists.llvm.org
Fri Aug 23 16:18:26 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: John Harrison (ashgti)

<details>
<summary>Changes</summary>

Refactoring `stackTrace` to perform frame look ups in a more on-demand fashion to improve overall performance.

Additionally adding additional information to the `exceptionInfo` request to report exception stacks there instead of merging the exception stack into the stack trace. The `exceptionInfo` request is only called if a stop event occurs with `reason='exception'`, which should mitigate the performance of `SBThread::GetCurrentException` calls.

Adding unit tests for exception handling and stack trace supporting.

---

Patch is 32.45 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/105905.diff


22 Files Affected:

- (modified) lldb/packages/Python/lldbsuite/test/lldbplatformutil.py (+16) 
- (modified) lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py (+11) 
- (modified) lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py (+7-2) 
- (modified) lldb/test/API/tools/lldb-dap/exception/Makefile (+1-1) 
- (modified) lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py (+5-3) 
- (added) lldb/test/API/tools/lldb-dap/exception/cpp/Makefile (+3) 
- (added) lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py (+26) 
- (added) lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp (+6) 
- (renamed) lldb/test/API/tools/lldb-dap/exception/main.c (+1-1) 
- (added) lldb/test/API/tools/lldb-dap/exception/objc/Makefile (+9) 
- (added) lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py (+27) 
- (added) lldb/test/API/tools/lldb-dap/exception/objc/main.m (+8) 
- (added) lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile (+5) 
- (added) lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py (+69) 
- (added) lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m (+28) 
- (modified) lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py (+1-3) 
- (modified) lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py (-5) 
- (modified) lldb/tools/lldb-dap/DAP.cpp (-1) 
- (modified) lldb/tools/lldb-dap/DAP.h (+1-1) 
- (modified) lldb/tools/lldb-dap/JSONUtils.cpp (+40) 
- (modified) lldb/tools/lldb-dap/JSONUtils.h (+3) 
- (modified) lldb/tools/lldb-dap/lldb-dap.cpp (+182-71) 


``````````diff
diff --git a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py
index 602e15d207e94a..3d8c713562e9bf 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py
@@ -181,6 +181,22 @@ def findMainThreadCheckerDylib():
     return ""
 
 
+def findBacktraceRecordingDylib():
+    if not platformIsDarwin():
+        return ""
+
+    if getPlatform() in lldbplatform.translate(lldbplatform.darwin_embedded):
+        return "/Developer/usr/lib/libBacktraceRecording.dylib"
+
+    with os.popen("xcode-select -p") as output:
+        xcode_developer_path = output.read().strip()
+        mtc_dylib_path = "%s/usr/lib/libBacktraceRecording.dylib" % xcode_developer_path
+        if os.path.isfile(mtc_dylib_path):
+            return mtc_dylib_path
+
+    return ""
+
+
 class _PlatformContext(object):
     """Value object class which contains platform-specific options."""
 
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 874383a13e2bb6..167142779cf12c 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -707,6 +707,17 @@ def request_evaluate(self, expression, frameIndex=0, threadId=None, context=None
         }
         return self.send_recv(command_dict)
 
+    def request_exceptionInfo(self, threadId=None):
+        if threadId is None:
+            threadId = self.get_thread_id()
+        args_dict = {"threadId": threadId}
+        command_dict = {
+            "command": "exceptionInfo",
+            "type": "request",
+            "arguments": args_dict,
+        }
+        return self.send_recv(command_dict)
+
     def request_initialize(self, sourceInitFile):
         command_dict = {
             "command": "initialize",
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 86eba355da83db..40d61636380588 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
@@ -100,13 +100,14 @@ def verify_breakpoint_hit(self, breakpoint_ids):
                         return
         self.assertTrue(False, "breakpoint not hit")
 
-    def verify_stop_exception_info(self, expected_description):
+    def verify_stop_exception_info(self, expected_description, timeout=timeoutval):
         """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()
+        stopped_events = self.dap_server.wait_for_stopped(timeout=timeout)
         for stopped_event in stopped_events:
+            print("stopped_event", stopped_event)
             if "body" in stopped_event:
                 body = stopped_event["body"]
                 if "reason" not in body:
@@ -177,6 +178,10 @@ def get_stackFrames(self, threadId=None, startFrame=None, levels=None, dump=Fals
         )
         return stackFrames
 
+    def get_exceptionInfo(self, threadId=None):
+        response = self.dap_server.request_exceptionInfo(threadId=threadId)
+        return self.get_dict_value(response, ["body"])
+
     def get_source_and_line(self, threadId=None, frameIndex=0):
         stackFrames = self.get_stackFrames(
             threadId=threadId, startFrame=frameIndex, levels=1
diff --git a/lldb/test/API/tools/lldb-dap/exception/Makefile b/lldb/test/API/tools/lldb-dap/exception/Makefile
index 99998b20bcb050..10495940055b63 100644
--- a/lldb/test/API/tools/lldb-dap/exception/Makefile
+++ b/lldb/test/API/tools/lldb-dap/exception/Makefile
@@ -1,3 +1,3 @@
-CXX_SOURCES := main.cpp
+C_SOURCES := main.c
 
 include Makefile.rules
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 8c2c0154ba65c0..39d73737b7e8c0 100644
--- a/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py
+++ b/lldb/test/API/tools/lldb-dap/exception/TestDAP_exception.py
@@ -1,5 +1,5 @@
 """
-Test exception behavior in DAP
+Test exception behavior in DAP with signal.
 """
 
 
@@ -16,8 +16,10 @@ def test_stopped_description(self):
         event.
         """
         program = self.getBuildArtifact("a.out")
-        print("test_stopped_description called", flush=True)
         self.build_and_launch(program)
-
         self.dap_server.request_continue()
         self.assertTrue(self.verify_stop_exception_info("signal SIGABRT"))
+        exceptionInfo = self.get_exceptionInfo()
+        self.assertEqual(exceptionInfo["breakMode"], "always")
+        self.assertEqual(exceptionInfo["description"], "signal SIGABRT")
+        self.assertEqual(exceptionInfo["exceptionId"], "signal")
diff --git a/lldb/test/API/tools/lldb-dap/exception/cpp/Makefile b/lldb/test/API/tools/lldb-dap/exception/cpp/Makefile
new file mode 100644
index 00000000000000..99998b20bcb050
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/cpp/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
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
new file mode 100644
index 00000000000000..6471e2b87251a7
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/cpp/TestDAP_exception_cpp.py
@@ -0,0 +1,26 @@
+"""
+Test exception behavior in DAP with c++ throw.
+"""
+
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbdap_testcase
+
+
+class TestDAP_exception_cpp(lldbdap_testcase.DAPTestCaseBase):
+    @skipIfWindows
+    def test_stopped_description(self):
+        """
+        Test that exception description is shown correctly in stopped
+        event.
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        self.dap_server.request_continue()
+        self.assertTrue(self.verify_stop_exception_info("signal SIGABRT"))
+        exceptionInfo = self.get_exceptionInfo()
+        self.assertEqual(exceptionInfo["breakMode"], "always")
+        self.assertEqual(exceptionInfo["description"], "signal SIGABRT")
+        self.assertEqual(exceptionInfo["exceptionId"], "signal")
+        self.assertIsNotNone(exceptionInfo["details"])
diff --git a/lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp b/lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp
new file mode 100644
index 00000000000000..39d89b95319a8c
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/cpp/main.cpp
@@ -0,0 +1,6 @@
+#include <stdexcept>
+
+int main(int argc, char const *argv[]) {
+  throw std::invalid_argument("throwing exception for testing");
+  return 0;
+}
diff --git a/lldb/test/API/tools/lldb-dap/exception/main.cpp b/lldb/test/API/tools/lldb-dap/exception/main.c
similarity index 56%
rename from lldb/test/API/tools/lldb-dap/exception/main.cpp
rename to lldb/test/API/tools/lldb-dap/exception/main.c
index b940d07c6f2bb3..a653ac5d82aa3a 100644
--- a/lldb/test/API/tools/lldb-dap/exception/main.cpp
+++ b/lldb/test/API/tools/lldb-dap/exception/main.c
@@ -1,6 +1,6 @@
 #include <signal.h>
 
-int main() {
+int main(int argc, char const *argv[]) {
   raise(SIGABRT);
   return 0;
 }
diff --git a/lldb/test/API/tools/lldb-dap/exception/objc/Makefile b/lldb/test/API/tools/lldb-dap/exception/objc/Makefile
new file mode 100644
index 00000000000000..9b6528337cb9d8
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/objc/Makefile
@@ -0,0 +1,9 @@
+OBJC_SOURCES := main.m
+
+CFLAGS_EXTRAS := -w
+
+USE_SYSTEM_STDLIB := 1
+
+LD_EXTRAS := -framework Foundation
+
+include Makefile.rules
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
new file mode 100644
index 00000000000000..777d55f48e8504
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/objc/TestDAP_exception_objc.py
@@ -0,0 +1,27 @@
+"""
+Test exception behavior in DAP with obj-c throw.
+"""
+
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+import lldbdap_testcase
+
+
+class TestDAP_exception_objc(lldbdap_testcase.DAPTestCaseBase):
+    @skipUnlessDarwin
+    def test_stopped_description(self):
+        """
+        Test that exception description is shown correctly in stopped event.
+        """
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        self.dap_server.request_continue()
+        self.assertTrue(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.assertEqual(exception_info["exceptionId"], "signal")
+        exception_details = exception_info["details"]
+        self.assertRegex(exception_details["message"], "SomeReason")
+        self.assertRegex(exception_details["stackTrace"], "main.m")
diff --git a/lldb/test/API/tools/lldb-dap/exception/objc/main.m b/lldb/test/API/tools/lldb-dap/exception/objc/main.m
new file mode 100644
index 00000000000000..e8db04fb40de15
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/exception/objc/main.m
@@ -0,0 +1,8 @@
+#import <Foundation/Foundation.h>
+
+int main(int argc, char const *argv[]) {
+  @throw [[NSException alloc] initWithName:@"ThrownException"
+                                    reason:@"SomeReason"
+                                  userInfo:nil];
+  return 0;
+}
diff --git a/lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile b/lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile
new file mode 100644
index 00000000000000..e4ee1a0506c0cf
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/extendedStackTrace/Makefile
@@ -0,0 +1,5 @@
+OBJC_SOURCES := main.m
+
+USE_SYSTEM_STDLIB := 1
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py b/lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py
new file mode 100644
index 00000000000000..efc907085b2c21
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/extendedStackTrace/TestDAP_extendedStackTrace.py
@@ -0,0 +1,69 @@
+"""
+Test lldb-dap stackTrace request with an extended backtrace thread.
+"""
+
+
+import os
+
+import lldbdap_testcase
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbplatformutil import *
+
+
+class TestDAP_extendedStackTrace(lldbdap_testcase.DAPTestCaseBase):
+    @skipUnlessDarwin
+    def test_stackTrace(self):
+        """
+        Tests the 'stackTrace' packet on a thread with an extended backtrace.
+        """
+        backtrace_recording_lib = findBacktraceRecordingDylib()
+        if not backtrace_recording_lib:
+            self.skipTest(
+                "Skipped because libBacktraceRecording.dylib was present on the system."
+            )
+
+        if not os.path.isfile("/usr/lib/system/introspection/libdispatch.dylib"):
+            self.skipTest(
+                "Skipped because introspection libdispatch dylib is not present."
+            )
+
+        program = self.getBuildArtifact("a.out")
+
+        self.build_and_launch(
+            program,
+            env=[
+                "DYLD_LIBRARY_PATH=/usr/lib/system/introspection",
+                "DYLD_INSERT_LIBRARIES=" + backtrace_recording_lib,
+            ],
+        )
+        source = "main.m"
+        breakpoint = line_number(source, "breakpoint 1")
+        lines = [breakpoint]
+
+        breakpoint_ids = self.set_source_breakpoints(source, lines)
+        self.assertEqual(
+            len(breakpoint_ids), len(lines), "expect correct number of breakpoints"
+        )
+
+        events = self.continue_to_next_stop()
+        print("huh", events)
+        stackFrames = self.get_stackFrames(threadId=events[0]["body"]["threadId"])
+        self.assertGreaterEqual(len(stackFrames), 3, "expect >= 3 frames")
+        self.assertEqual(stackFrames[0]["name"], "one")
+        self.assertEqual(stackFrames[1]["name"], "two")
+        self.assertEqual(stackFrames[2]["name"], "three")
+
+        stackLabels = [
+            frame
+            for frame in stackFrames
+            if frame.get("presentationHint", "") == "label"
+        ]
+        self.assertEqual(len(stackLabels), 2, "expected two label stack frames")
+        self.assertRegex(
+            stackLabels[0]["name"],
+            "Enqueued from com.apple.root.default-qos \(Thread \d\)",
+        )
+        self.assertRegex(
+            stackLabels[1]["name"], "Enqueued from com.apple.main-thread \(Thread \d\)"
+        )
diff --git a/lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m b/lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m
new file mode 100644
index 00000000000000..d513880236c517
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/extendedStackTrace/main.m
@@ -0,0 +1,28 @@
+#import <dispatch/dispatch.h>
+#include <stdio.h>
+
+void one() {
+  printf("one...\n"); // breakpoint 1
+}
+
+void two() {
+  printf("two...\n");
+  one();
+}
+
+void three() {
+  printf("three...\n");
+  two();
+}
+
+int main(int argc, char *argv[]) {
+  printf("main...\n");
+  // Nest from main queue > global queue > main queue.
+  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
+                 ^{
+                   dispatch_async(dispatch_get_main_queue(), ^{
+                     three();
+                   });
+                 });
+  dispatch_main();
+}
diff --git a/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py b/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py
index 0d7776faa4a9de..fad5419140f454 100644
--- a/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py
+++ b/lldb/test/API/tools/lldb-dap/stackTrace/TestDAP_stackTrace.py
@@ -1,13 +1,11 @@
 """
-Test lldb-dap setBreakpoints request
+Test lldb-dap stackTrace request
 """
 
 
 import os
 
-import dap_server
 import lldbdap_testcase
-from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 
diff --git a/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py b/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py
index a04c752764fbb2..f2131d6a821217 100644
--- a/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py
+++ b/lldb/test/API/tools/lldb-dap/stackTraceMissingFunctionName/TestDAP_stackTraceMissingFunctionName.py
@@ -2,13 +2,8 @@
 Test lldb-dap stack trace response
 """
 
-
-import dap_server
 from lldbsuite.test.decorators import *
-import os
-
 import lldbdap_testcase
-from lldbsuite.test import lldbtest, lldbutil
 
 
 class TestDAP_stackTraceMissingFunctionName(lldbdap_testcase.DAPTestCaseBase):
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 57b93c28ce9301..1fd560f21904ab 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -36,7 +36,6 @@ DAP::DAP()
       focus_tid(LLDB_INVALID_THREAD_ID), stop_at_entry(false), is_attach(false),
       enable_auto_variable_summaries(false),
       enable_synthetic_child_debugging(false),
-      enable_display_extended_backtrace(false),
       restarting_process_id(LLDB_INVALID_PROCESS_ID),
       configuration_done_sent(false), waiting_for_run_in_terminal(false),
       progress_event_reporter(
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 0fc77ac1e81683..c621123f18097f 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -181,7 +181,6 @@ struct DAP {
   bool is_attach;
   bool enable_auto_variable_summaries;
   bool enable_synthetic_child_debugging;
-  bool enable_display_extended_backtrace;
   // The process event thread normally responds to process exited events by
   // shutting down the entire adapter. When we're restarting, we keep the id of
   // the old process here so we can detect this case and keep running.
@@ -193,6 +192,7 @@ struct DAP {
   // Keep track of the last stop thread index IDs as threads won't go away
   // unless we send a "thread" event to indicate the thread exited.
   llvm::DenseSet<lldb::tid_t> thread_ids;
+  std::map<lldb::tid_t, uint32_t> thread_stack_size_cache;
   uint32_t reverse_request_seq;
   std::mutex call_mutex;
   std::map<int /* request_seq */, ResponseCallback /* reply handler */>
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index a8b85f55939e17..dafe54a49186e0 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -1257,6 +1257,46 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
   return llvm::json::Value(std::move(object));
 }
 
+// "ExceptionDetails": {
+//   "type": "object",
+//   "description": "Detailed information about an exception that has
+//   occurred.", "properties": {
+//     "message": {
+//       "type": "string",
+//       "description": "Message contained in the exception."
+//     },
+//     "typeName": {
+//       "type": "string",
+//       "description": "Short type name of the exception object."
+//     },
+//     "fullTypeName": {
+//       "type": "string",
+//       "description": "Fully-qualified type name of the exception object."
+//     },
+//     "evaluateName": {
+//       "type": "string",
+//       "description": "An expression that can be evaluated in the current
+//       scope to obtain the exception object."
+//     },
+//     "stackTrace": {
+//       "type": "string",
+//       "description": "Stack trace at the time the exception was thrown."
+//     },
+//     "innerException": {
+//       "type": "array",
+//       "items": {
+//         "$ref": "#/definitions/ExceptionDetails"
+//       },
+//       "description": "Details of the exception contained by this exception,
+//       if any."
+//     }
+//   }
+// },
+llvm::json::Value CreateExceptionDetails() {
+  llvm::json::Object object;
+  return llvm::json::Value(std::move(object));
+}
+
 llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit) {
   llvm::json::Object object;
   char unit_path_arr[PATH_MAX];
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index 1515f5ba2e5f4d..88df05756a0eaa 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -467,6 +467,9 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
                                  bool is_name_duplicated = false,
                                  std::optional<std::string> custom_name = {});
 
+/// Create a "ExceptionDetail" object for a LLDB
+llvm::json::Value CreateExceptionDetails();
+
 llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit);
 
 /// Create a runInTerminal reverse request object
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 495ed0256120e8..aa34c275fad589 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -701,8 +701,6 @@ void request_attach(const llvm::json::Object &request) {
       GetBoolean(arguments, "enableAutoVariableSummaries", false);
   g_dap.enable_synthetic_child_debugging =
       GetBoolean(arguments, "enableSyntheticChildDebugging", false);
-  g_dap.enable_display_extended_backtrace =
-      GetBoolean(arguments, "enableDisplayExtendedBacktrace", false);
   g_dap.command_escape_prefix =
       GetString(arguments, "commandEscapePrefix", "`");
   g_dap.SetFrameFormat(GetString(arguments, "customFrameFormat"));
@@ -1020,6 +1018,68 @@ void request_disconnect(const llvm::json::Object &request) {
   g_dap.disconnecting = true;
 }
 
+// "ExceptionInfoRequest": {
+//   "allOf": [ { "$ref": "#/definitions/Request" }, {
+//     "type": "object",
+//     "description": "Retrieves the details of the exception that
+//     caused this event to be raised. Clients should only call this request if
+//     the corresponding capability `supportsExceptionInfoR...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/105905


More information about the lldb-commits mailing list