Skip to content

Commit c54157f

Browse files
committed
[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.
1 parent a7d578d commit c54157f

File tree

2 files changed

+47
-15
lines changed

2 files changed

+47
-15
lines changed

lldb/tools/lldb-dap/JSONUtils.cpp

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
#include "llvm/Support/ScopedPrinter.h"
4646
#include "llvm/Support/raw_ostream.h"
4747
#include <chrono>
48-
#include <climits>
4948
#include <cstddef>
5049
#include <iomanip>
5150
#include <optional>
@@ -698,14 +697,22 @@ llvm::json::Value CreateSource(llvm::StringRef source_path) {
698697
return llvm::json::Value(std::move(source));
699698
}
700699

701-
static std::optional<llvm::json::Value> CreateSource(lldb::SBFrame &frame) {
700+
static llvm::json::Value CreateSource(lldb::SBFrame &frame,
701+
llvm::StringRef frame_name) {
702702
auto line_entry = frame.GetLineEntry();
703703
// A line entry of 0 indicates the line is compiler generated i.e. no source
704704
// file is associated with the frame.
705705
if (line_entry.GetFileSpec().IsValid() && line_entry.GetLine() != 0)
706706
return CreateSource(line_entry);
707707

708-
return {};
708+
llvm::json::Object source;
709+
EmplaceSafeString(source, "name", frame_name);
710+
source.try_emplace("sourceReference", MakeDAPFrameID(frame));
711+
// If we don't have a filespec then we don't have the original source. Mark
712+
// the source as deemphasized since users will only be able to view assembly
713+
// for these frames.
714+
EmplaceSafeString(source, "presentationHint", "deemphasize");
715+
return std::move(source);
709716
}
710717

711718
// "StackFrame": {
@@ -799,21 +806,22 @@ llvm::json::Value CreateStackFrame(lldb::SBFrame &frame,
799806

800807
EmplaceSafeString(object, "name", frame_name);
801808

802-
auto source = CreateSource(frame);
803-
804-
if (source) {
805-
object.try_emplace("source", *source);
806-
auto line_entry = frame.GetLineEntry();
807-
auto line = line_entry.GetLine();
808-
if (line && line != LLDB_INVALID_LINE_NUMBER)
809-
object.try_emplace("line", line);
810-
else
811-
object.try_emplace("line", 0);
809+
object.try_emplace("source", CreateSource(frame, frame_name));
810+
auto line_entry = frame.GetLineEntry();
811+
if (line_entry.IsValid() &&
812+
(line_entry.GetLine() != 0 ||
813+
line_entry.GetLine() != LLDB_INVALID_LINE_NUMBER)) {
814+
object.try_emplace("line", line_entry.GetLine());
812815
auto column = line_entry.GetColumn();
813816
object.try_emplace("column", column);
814817
} else {
815-
object.try_emplace("line", 0);
816-
object.try_emplace("column", 0);
818+
lldb::addr_t inst_offset = frame.GetPCAddress().GetOffset() -
819+
frame.GetSymbol().GetStartAddress().GetOffset();
820+
lldb::addr_t inst_line =
821+
inst_offset / (frame.GetThread().GetProcess().GetAddressByteSize() / 2);
822+
// lines are base-1 indexed
823+
object.try_emplace("line", inst_line + 1);
824+
object.try_emplace("column", 1);
817825
}
818826

819827
const auto pc = frame.GetPC();

lldb/tools/lldb-dap/lldb-dap.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "RunInTerminal.h"
1414
#include "Watchpoint.h"
1515
#include "lldb/API/SBDeclaration.h"
16+
#include "lldb/API/SBDefines.h"
1617
#include "lldb/API/SBEvent.h"
1718
#include "lldb/API/SBFile.h"
1819
#include "lldb/API/SBInstruction.h"
@@ -3431,6 +3432,29 @@ void request_source(DAP &dap, const llvm::json::Object &request) {
34313432
llvm::json::Object response;
34323433
FillResponse(request, response);
34333434
llvm::json::Object body{{"content", ""}};
3435+
3436+
const auto *arguments = request.getObject("arguments");
3437+
const auto *source = arguments->getObject("source");
3438+
int64_t source_ref = GetUnsigned(
3439+
source, "sourceReference", GetUnsigned(arguments, "sourceReference", 0));
3440+
3441+
lldb::SBProcess process = dap.target.GetProcess();
3442+
// Upper 32 bits is the thread index ID
3443+
lldb::SBThread thread =
3444+
process.GetThreadByIndexID(GetLLDBThreadIndexID(source_ref));
3445+
// Lower 32 bits is the frame index
3446+
lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(source_ref));
3447+
if (!frame.IsValid()) {
3448+
response["success"] = false;
3449+
response["message"] = "source not found";
3450+
} else {
3451+
lldb::SBInstructionList insts = frame.GetSymbol().GetInstructions(dap.target);
3452+
lldb::SBStream stream;
3453+
insts.GetDescription(stream);
3454+
body["content"] = stream.GetData();
3455+
body["mimeType"] = "text/x-lldb.disassembly";
3456+
}
3457+
34343458
response.try_emplace("body", std::move(body));
34353459
dap.SendJSON(llvm::json::Value(std::move(response)));
34363460
}

0 commit comments

Comments
 (0)