================
@@ -7,14 +7,105 @@
 
//===----------------------------------------------------------------------===//
 
 #include "DAP.h"
+#include "DAPError.h"
 #include "EventHelper.h"
-#include "JSONUtils.h"
+#include "LLDBUtils.h"
+#include "Protocol/ProtocolRequests.h"
+#include "ProtocolUtils.h"
 #include "RequestHandler.h"
+#include "lldb/API/SBStream.h"
 
-namespace lldb_dap {
+using namespace lldb_dap;
+using namespace lldb_dap::protocol;
 
-/// Page size used for reporting addtional frames in the 'stackTrace' request.
-static constexpr int StackPageSize = 20;
+/// Page size used for reporting additional frames in the 'stackTrace' request.
+static constexpr int k_stack_page_size = 20;
+
+// Create a "StackFrame" object for a LLDB frame object.
+static StackFrame CreateStackFrame(DAP &dap, lldb::SBFrame &frame,
+                                   lldb::SBFormat &format) {
+  StackFrame stack_frame;
+  stack_frame.id = MakeDAPFrameID(frame);
+
+  lldb::SBStream stream;
+  if (format && frame.GetDescriptionWithFormat(format, stream).Success()) {
+    stack_frame.name = stream.GetData();
+
+    // `function_name` can be a nullptr, which throws an error when assigned to
+    // an `std::string`.
+  } else if (const char *name = frame.GetDisplayFunctionName()) {
+    stack_frame.name = name;
+  }
+
+  if (stack_frame.name.empty()) {
+    // If the function name is unavailable, display the pc address as a 
16-digit
+    // hex string, e.g. "0x0000000000012345"
+    stack_frame.name = GetLoadAddressString(frame.GetPC());
+  }
+
+  // We only include `[opt]` if a custom frame format is not specified.
+  if (!format && frame.GetFunction().GetIsOptimized())
+    stack_frame.name += " [opt]";
+
+  std::optional<protocol::Source> source = dap.ResolveSource(frame);
+  if (source && !IsAssemblySource(*source)) {
+    // This is a normal source with a valid line entry.
+    auto line_entry = frame.GetLineEntry();
+    stack_frame.line = line_entry.GetLine();
+    stack_frame.column = line_entry.GetColumn();
+  } else if (frame.GetSymbol().IsValid()) {
+    // This is a source where the disassembly is used, but there is a valid
+    // symbol. Calculate the line of the current PC from the start of the
+    // current symbol.
+    lldb::SBInstructionList inst_list = dap.target.ReadInstructions(
+        frame.GetSymbol().GetStartAddress(), frame.GetPCAddress(), nullptr);
+    size_t inst_line = inst_list.GetSize();
+
+    // Line numbers are 1-based.
+    stack_frame.line = inst_line + 1;
+    stack_frame.column = 1;
+  } else {
+    // No valid line entry or symbol.
+    stack_frame.line = 1;
+    stack_frame.column = 1;
----------------
ashgti wrote:

Should these set the line/column to 0? Or in the toJSON, these will be set to 
zero if source is empty. It feels like we could run into an internal logic 
error if this is set and the source field is empty.

Maybe we could add an assert to the toJSON so if `source` is set, at least 
`line` must also be set and if `source` is empty then `line` should be `0`.

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

Reply via email to