ashgti created this revision. Herald added a project: All. ashgti requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D156465 Files: lldb/tools/lldb-vscode/JSONUtils.cpp lldb/tools/lldb-vscode/lldb-vscode.cpp
Index: lldb/tools/lldb-vscode/lldb-vscode.cpp =================================================================== --- lldb/tools/lldb-vscode/lldb-vscode.cpp +++ lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -2687,13 +2687,61 @@ 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)); Index: lldb/tools/lldb-vscode/JSONUtils.cpp =================================================================== --- lldb/tools/lldb-vscode/JSONUtils.cpp +++ lldb/tools/lldb-vscode/JSONUtils.cpp @@ -815,17 +815,30 @@ 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)); }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits