Skip to content

Commit 49b6f7b

Browse files
committed
[lldb][lldb-dap] use breakpoints to verify goto location.
1 parent 76d5565 commit 49b6f7b

File tree

2 files changed

+72
-29
lines changed

2 files changed

+72
-29
lines changed

lldb/tools/lldb-dap/Handler/GoToRequestHandler.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace lldb_dap {
1414

1515
/// Creates an \p StoppedEvent with the reason \a goto
1616
static void SendThreadGotoEvent(DAP &dap, lldb::tid_t thread_id) {
17-
1817
llvm::json::Object event(CreateEventObject("stopped"));
1918
llvm::json::Object body;
2019
body.try_emplace("reason", "goto");

lldb/tools/lldb-dap/Handler/GoToTargetsRequestHandler.cpp

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,51 @@
1010

1111
#include "JSONUtils.h"
1212

13+
#include <lldb/API/SBBreakpointLocation.h>
14+
#include <lldb/API/SBListener.h>
1315
#include <lldb/API/SBStream.h>
1416

1517
namespace lldb_dap {
1618

19+
static llvm::SmallVector<lldb::SBLineEntry>
20+
GetLineValidEntry(DAP &dap, const lldb::SBFileSpec &file_spec, uint32_t line) {
21+
// disable breakpoint listeners so they do not send events to the DAP client.
22+
lldb::SBListener listener = dap.debugger.GetListener();
23+
lldb::SBBroadcaster broadcaster = dap.target.GetBroadcaster();
24+
constexpr auto event_mask = lldb::SBTarget::eBroadcastBitBreakpointChanged;
25+
listener.StopListeningForEvents(broadcaster, event_mask);
26+
27+
// create a breakpoint to resolve the line if it is on an empty line.
28+
lldb::SBBreakpoint goto_bp =
29+
dap.target.BreakpointCreateByLocation(file_spec, line);
30+
if (!goto_bp.IsValid())
31+
return {};
32+
33+
llvm::SmallVector<lldb::SBLineEntry> entry_locations{};
34+
const size_t resolved_count = goto_bp.GetNumResolvedLocations();
35+
for (size_t idx = 0; idx < resolved_count; ++idx) {
36+
lldb::SBBreakpointLocation location = goto_bp.GetLocationAtIndex(idx);
37+
if (!location.IsValid())
38+
continue;
39+
40+
lldb::SBAddress addr = location.GetAddress();
41+
if (!addr.IsValid())
42+
continue;
43+
44+
lldb::SBLineEntry line_entry = addr.GetLineEntry();
45+
if (!line_entry.IsValid())
46+
continue;
47+
48+
entry_locations.push_back(line_entry);
49+
}
50+
51+
// clean up;
52+
dap.target.BreakpointDelete(goto_bp.GetID());
53+
listener.StartListeningForEvents(broadcaster, event_mask);
54+
55+
return entry_locations;
56+
}
57+
1758
// "GotoTargetsRequest": {
1859
// "allOf": [ { "$ref": "#/definitions/Request" }, {
1960
// "type": "object",
@@ -83,37 +124,40 @@ void GoToTargetsRequestHandler::operator()(
83124
const llvm::json::Object &request) const {
84125
llvm::json::Object response;
85126
FillResponse(request, response);
86-
const auto *arguments = request.getObject("arguments");
87-
const auto *source = arguments->getObject("source");
88-
const std::string path = GetString(source, "path").str();
89-
90-
const auto goto_line = GetInteger<uint64_t>(arguments, "line").value_or(0u);
91-
const auto goto_column =
92-
GetInteger<uint64_t>(arguments, "column").value_or(0u);
93127

94-
lldb::SBLineEntry line_entry{};
128+
const llvm::json::Object *arguments = request.getObject("arguments");
129+
const llvm::json::Object *source = arguments->getObject("source");
130+
const std::string path = GetString(source, "path").str();
95131
const lldb::SBFileSpec file_spec(path.c_str(), true);
96-
line_entry.SetFileSpec(file_spec);
97-
line_entry.SetLine(goto_line);
98-
line_entry.SetColumn(goto_column);
99-
100-
const auto target_id = dap.goto_id_map.InsertLineEntry(line_entry);
101-
llvm::json::Array response_targets;
102-
const auto target_line = line_entry.GetLine();
103-
const auto target_column = line_entry.GetColumn();
104-
auto target = llvm::json::Object();
105-
target.try_emplace("id", target_id);
106-
107-
lldb::SBStream stream;
108-
line_entry.GetDescription(stream);
109-
target.try_emplace("label",
110-
llvm::StringRef(stream.GetData(), stream.GetSize()));
111-
target.try_emplace("column", target_column);
112-
target.try_emplace("line", target_line);
113-
114-
response_targets.push_back(std::move(target));
132+
const uint64_t goto_line =
133+
GetInteger<uint64_t>(arguments, "line").value_or(1U);
134+
115135
llvm::json::Object body;
116-
body.try_emplace("targets", std::move(response_targets));
136+
137+
llvm::SmallVector<lldb::SBLineEntry> goto_locations =
138+
GetLineValidEntry(dap, file_spec, goto_line);
139+
if (goto_locations.empty()) {
140+
response["success"] = false;
141+
response["message"] = "Invalid jump location";
142+
} else {
143+
llvm::json::Array response_targets;
144+
for (lldb::SBLineEntry &line_entry : goto_locations) {
145+
const uint64_t target_id = dap.goto_id_map.InsertLineEntry(line_entry);
146+
const uint32_t target_line = line_entry.GetLine();
147+
auto target = llvm::json::Object();
148+
target.try_emplace("id", target_id);
149+
150+
lldb::SBStream stream;
151+
line_entry.GetDescription(stream);
152+
target.try_emplace("label",
153+
llvm::StringRef(stream.GetData(), stream.GetSize()));
154+
target.try_emplace("line", target_line);
155+
response_targets.push_back(std::move(target));
156+
}
157+
158+
body.try_emplace("targets", std::move(response_targets));
159+
}
160+
117161
response.try_emplace("body", std::move(body));
118162
dap.SendJSON(llvm::json::Value(std::move(response)));
119163
}

0 commit comments

Comments
 (0)