[Lldb-commits] [lldb] [lldb-dap] Add 'source' references to stack frames without source files. (PR #128268)

John Harrison via lldb-commits lldb-commits at lists.llvm.org
Sat Feb 22 13:18:25 PST 2025


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

>From 2f7885cfac5d5049c317de56109eed3bd2579acc Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Fri, 21 Feb 2025 17:45:17 -0800
Subject: [PATCH 1/3] [lldb-dap] Add 'source' references to stack frames
 without source files.

This adds 'source' references to all stack frames. When opening a stack frame users will see the disassembly of the frame if the source is not available.

This works around the odd behavior of navigating frames without the VSCode disassembly view open, which causes 'step' to step in the first frame with a source instead of the active frame.
---
 lldb/tools/lldb-dap/JSONUtils.cpp | 38 +++++++++++++++++++------------
 lldb/tools/lldb-dap/lldb-dap.cpp  | 28 ++++++++++++++++++++---
 2 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 6ca4dfb4711a1..ee8fcef6f2503 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -45,7 +45,6 @@
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/raw_ostream.h"
 #include <chrono>
-#include <climits>
 #include <cstddef>
 #include <iomanip>
 #include <optional>
@@ -698,14 +697,22 @@ llvm::json::Value CreateSource(llvm::StringRef source_path) {
   return llvm::json::Value(std::move(source));
 }
 
-static std::optional<llvm::json::Value> CreateSource(lldb::SBFrame &frame) {
+static llvm::json::Value CreateSource(lldb::SBFrame &frame,
+                                      llvm::StringRef frame_name) {
   auto line_entry = frame.GetLineEntry();
   // A line entry of 0 indicates the line is compiler generated i.e. no source
   // file is associated with the frame.
   if (line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0)
     return CreateSource(line_entry);
 
-  return {};
+  llvm::json::Object source;
+  EmplaceSafeString(source, "name", frame_name);
+  source.try_emplace("sourceReference", MakeDAPFrameID(frame));
+  // If we don't have a filespec then we don't have the original source. Mark
+  // the source as deemphasized since users will only be able to view assembly
+  // for these frames.
+  EmplaceSafeString(source, "presentationHint", "deemphasize");
+  return std::move(source);
 }
 
 // "StackFrame": {
@@ -799,21 +806,22 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame,
 
   EmplaceSafeString(object, "name", frame_name);
 
-  auto source = CreateSource(frame);
-
-  if (source) {
-    object.try_emplace("source", *source);
-    auto line_entry = frame.GetLineEntry();
-    auto line = line_entry.GetLine();
-    if (line && line != LLDB_INVALID_LINE_NUMBER)
-      object.try_emplace("line", line);
-    else
-      object.try_emplace("line", 0);
+  object.try_emplace("source", CreateSource(frame, frame_name));
+  auto line_entry = frame.GetLineEntry();
+  if (line_entry.IsValid() &&
+      (line_entry.GetLine() != 0 ||
+       line_entry.GetLine() != LLDB_INVALID_LINE_NUMBER)) {
+    object.try_emplace("line", line_entry.GetLine());
     auto column = line_entry.GetColumn();
     object.try_emplace("column", column);
   } else {
-    object.try_emplace("line", 0);
-    object.try_emplace("column", 0);
+    lldb::addr_t inst_offset = frame.GetPCAddress().GetOffset() -
+                               frame.GetSymbol().GetStartAddress().GetOffset();
+    lldb::addr_t inst_line =
+        inst_offset / (frame.GetThread().GetProcess().GetAddressByteSize() / 2);
+    // lines are base-1 indexed
+    object.try_emplace("line", inst_line + 1);
+    object.try_emplace("column", 1);
   }
 
   const auto pc = frame.GetPC();
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index e323990d8b6ed..1da8358eb5224 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -13,7 +13,9 @@
 #include "RunInTerminal.h"
 #include "Watchpoint.h"
 #include "lldb/API/SBDeclaration.h"
+#include "lldb/API/SBDefines.h"
 #include "lldb/API/SBEvent.h"
+#include "lldb/API/SBFile.h"
 #include "lldb/API/SBInstruction.h"
 #include "lldb/API/SBListener.h"
 #include "lldb/API/SBMemoryRegionInfo.h"
@@ -38,9 +40,6 @@
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <array>
-#include <cassert>
-#include <climits>
-#include <cstdarg>
 #include <cstdint>
 #include <cstdio>
 #include <cstdlib>
@@ -3488,6 +3487,29 @@ void request_source(DAP &dap, const llvm::json::Object &request) {
   llvm::json::Object response;
   FillResponse(request, response);
   llvm::json::Object body{{"content", ""}};
+
+  const auto *arguments = request.getObject("arguments");
+  const auto *source = arguments->getObject("source");
+  int64_t source_ref = GetUnsigned(
+      source, "sourceReference", GetUnsigned(arguments, "sourceReference", 0));
+
+  lldb::SBProcess process = dap.target.GetProcess();
+  // Upper 32 bits is the thread index ID
+  lldb::SBThread thread =
+      process.GetThreadByIndexID(GetLLDBThreadIndexID(source_ref));
+  // Lower 32 bits is the frame index
+  lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(source_ref));
+  if (!frame.IsValid()) {
+    response["success"] = false;
+    response["message"] = "source not found";
+  } else {
+    lldb::SBInstructionList insts = frame.GetSymbol().GetInstructions(dap.target);
+    lldb::SBStream stream;
+    insts.GetDescription(stream);
+    body["content"] = stream.GetData();
+    body["mimeType"] = "text/x-lldb.disassembly";
+  }
+
   response.try_emplace("body", std::move(body));
   dap.SendJSON(llvm::json::Value(std::move(response)));
 }

>From da9a1673619935d26a5349d7131f5cc152b84d16 Mon Sep 17 00:00:00 2001
From: John Harrison <harjohn at google.com>
Date: Fri, 21 Feb 2025 18:27:59 -0800
Subject: [PATCH 2/3] Applying clang-format.

---
 lldb/tools/lldb-dap/lldb-dap.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 1da8358eb5224..a6db74cd3f860 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -3503,7 +3503,8 @@ void request_source(DAP &dap, const llvm::json::Object &request) {
     response["success"] = false;
     response["message"] = "source not found";
   } else {
-    lldb::SBInstructionList insts = frame.GetSymbol().GetInstructions(dap.target);
+    lldb::SBInstructionList insts =
+        frame.GetSymbol().GetInstructions(dap.target);
     lldb::SBStream stream;
     insts.GetDescription(stream);
     body["content"] = stream.GetData();

>From 585a5700078264d3bf27cab8b317775972f55183 Mon Sep 17 00:00:00 2001
From: John Harrison <ash at greaterthaninfinity.com>
Date: Sat, 22 Feb 2025 13:18:18 -0800
Subject: [PATCH 3/3] Apply suggestions from code review

Co-authored-by: Jonas Devlieghere <jonas at devlieghere.com>
---
 lldb/tools/lldb-dap/JSONUtils.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index ee8fcef6f2503..86e5852b9a6c9 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -819,7 +819,7 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame,
                                frame.GetSymbol().GetStartAddress().GetOffset();
     lldb::addr_t inst_line =
         inst_offset / (frame.GetThread().GetProcess().GetAddressByteSize() / 2);
-    // lines are base-1 indexed
+    // Line numbers are 1-based. 
     object.try_emplace("line", inst_line + 1);
     object.try_emplace("column", 1);
   }



More information about the lldb-commits mailing list