[Lldb-commits] [lldb] 1bf6f55 - [lldb-vscode] Adding support for displaying backtraces.

David Goldman via lldb-commits lldb-commits at lists.llvm.org
Fri Jul 28 13:55:11 PDT 2023


Author: John Harrison
Date: 2023-07-28T16:54:27-04:00
New Revision: 1bf6f55911ca6427789093b1df8a63d7e72dac51

URL: https://github.com/llvm/llvm-project/commit/1bf6f55911ca6427789093b1df8a63d7e72dac51
DIFF: https://github.com/llvm/llvm-project/commit/1bf6f55911ca6427789093b1df8a63d7e72dac51.diff

LOG: [lldb-vscode] Adding support for displaying backtraces.

On Apple platforms when debugging with libBacktraceRecording.dylib backtraces are stored as part of the thread stack. This change includes support for displaying the back traces when they are present in the stack trace.

To use this on macOS a binary needs to be run with the following environment variables configured:

DYLD_LIBRARY_PATH=/usr/lib/system/introspection
DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib
{F28473587}

Reviewed By: wallace

Differential Revision: https://reviews.llvm.org/D156465

Added: 
    

Modified: 
    lldb/tools/lldb-vscode/JSONUtils.cpp
    lldb/tools/lldb-vscode/lldb-vscode.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp
index 98dbba32b033e3..06359e1c76ff91 100644
--- a/lldb/tools/lldb-vscode/JSONUtils.cpp
+++ b/lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -815,17 +815,30 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame) {
 llvm::json::Value CreateThread(lldb::SBThread &thread) {
   llvm::json::Object object;
   object.try_emplace("id", (int64_t)thread.GetThreadID());
-  char thread_str[64];
-  snprintf(thread_str, sizeof(thread_str), "Thread #%u", thread.GetIndexID());
-  const char *name = thread.GetName();
-  if (name) {
-    std::string thread_with_name(thread_str);
-    thread_with_name += ' ';
-    thread_with_name += name;
-    EmplaceSafeString(object, "name", thread_with_name);
+  const char *thread_name = thread.GetName();
+  const char *queue_name = thread.GetQueueName();
+
+  std::string thread_str;
+  if (thread_name) {
+    thread_str = std::string(thread_name);
+  } else if (queue_name) {
+    auto kind = thread.GetQueue().GetKind();
+    std::string queue_kind_label = "";
+    if (kind == lldb::eQueueKindSerial) {
+      queue_kind_label = " (serial)";
+    } else if (kind == lldb::eQueueKindConcurrent) {
+      queue_kind_label = " (concurrent)";
+    }
+
+    thread_str = llvm::formatv("Thread {0} Queue: {1}{2}", thread.GetIndexID(),
+                               queue_name, queue_kind_label)
+                     .str();
   } else {
-    EmplaceSafeString(object, "name", std::string(thread_str));
+    thread_str = llvm::formatv("Thread {0}", thread.GetIndexID()).str();
   }
+
+  EmplaceSafeString(object, "name", thread_str);
+
   return llvm::json::Value(std::move(object));
 }
 

diff  --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 72ebe4825024e3..4421202566066f 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -2687,13 +2687,72 @@ void request_stackTrace(const llvm::json::Object &request) {
     const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
     const auto levels = GetUnsigned(arguments, "levels", 0);
     const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
+    auto totalFrames = thread.GetNumFrames();
+
+    // This will always return an invalid thread when
+    // libBacktraceRecording.dylib is not loaded or if there is no extended
+    // backtrace.
+    lldb::SBThread queue_backtrace_thread =
+        thread.GetExtendedBacktraceThread("libdispatch");
+    if (queue_backtrace_thread.IsValid()) {
+      // One extra frame as a label to mark the enqueued thread.
+      totalFrames += queue_backtrace_thread.GetNumFrames() + 1;
+    }
+
+    // This will always return an invalid thread when there is no exception in
+    // the current thread.
+    lldb::SBThread exception_backtrace_thread =
+        thread.GetCurrentExceptionBacktrace();
+    if (exception_backtrace_thread.IsValid()) {
+      // One extra frame as a label to mark the exception thread.
+      totalFrames += exception_backtrace_thread.GetNumFrames() + 1;
+    }
+
     for (uint32_t i = startFrame; i < endFrame; ++i) {
-      auto frame = thread.GetFrameAtIndex(i);
+      lldb::SBFrame frame;
+      std::string prefix;
+      if (i < thread.GetNumFrames()) {
+        frame = thread.GetFrameAtIndex(i);
+      } else if (queue_backtrace_thread.IsValid() &&
+                 i < (thread.GetNumFrames() +
+                      queue_backtrace_thread.GetNumFrames() + 1)) {
+        if (i == thread.GetNumFrames()) {
+          const uint32_t thread_idx =
+              queue_backtrace_thread.GetExtendedBacktraceOriginatingIndexID();
+          const char *queue_name = queue_backtrace_thread.GetQueueName();
+          auto name = llvm::formatv("Enqueued from {0} (Thread {1})",
+                                    queue_name, thread_idx);
+          stackFrames.emplace_back(
+              llvm::json::Object{{"id", thread.GetThreadID() + 1},
+                                 {"name", name},
+                                 {"presentationHint", "label"}});
+          continue;
+        }
+        frame = queue_backtrace_thread.GetFrameAtIndex(
+            i - thread.GetNumFrames() - 1);
+      } else if (exception_backtrace_thread.IsValid()) {
+        if (i == thread.GetNumFrames() +
+                     (queue_backtrace_thread.IsValid()
+                          ? queue_backtrace_thread.GetNumFrames() + 1
+                          : 0)) {
+          stackFrames.emplace_back(
+              llvm::json::Object{{"id", thread.GetThreadID() + 2},
+                                 {"name", "Original Exception Backtrace"},
+                                 {"presentationHint", "label"}});
+          continue;
+        }
+
+        frame = exception_backtrace_thread.GetFrameAtIndex(
+            i - thread.GetNumFrames() -
+            (queue_backtrace_thread.IsValid()
+                 ? queue_backtrace_thread.GetNumFrames() + 1
+                 : 0));
+      }
       if (!frame.IsValid())
         break;
       stackFrames.emplace_back(CreateStackFrame(frame));
     }
-    const auto totalFrames = thread.GetNumFrames();
+
     body.try_emplace("totalFrames", totalFrames);
   }
   body.try_emplace("stackFrames", std::move(stackFrames));


        


More information about the lldb-commits mailing list