Skip to content

Commit ee49203

Browse files
committed
support assembly in SetBreakpointsRequestHandler
1 parent d6325b3 commit ee49203

File tree

6 files changed

+127
-16
lines changed

6 files changed

+127
-16
lines changed

lldb/tools/lldb-dap/DAP.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ struct DAP {
169169
Variables variables;
170170
lldb::SBBroadcaster broadcaster;
171171
llvm::StringMap<SourceBreakpointMap> source_breakpoints;
172+
llvm::DenseMap<int64_t, SourceBreakpointMap> assembly_breakpoints;
172173
FunctionBreakpointMap function_breakpoints;
173174
InstructionBreakpointMap instruction_breakpoints;
174175
std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;

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

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,14 @@ void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
117117
return;
118118

119119
lldb::SBSymbol symbol = frame.GetSymbol();
120-
if (symbol.IsValid()) {
121-
lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
122-
for (uint32_t i = start_line - 1; i < insts.GetSize() && i < (end_line - 1);
123-
++i) {
124-
locations.emplace_back(i, 0);
125-
}
126-
} else {
127-
for (uint32_t i = start_line - 1;
128-
i < dap.number_of_assembly_lines_for_nodebug && i < (end_line - 1);
129-
++i) {
130-
locations.emplace_back(i, 0);
131-
}
120+
if (!symbol.IsValid())
121+
return;
122+
123+
// start_line is relative to the symbol's start address
124+
lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
125+
for (uint32_t i = start_line - 1; i < insts.GetSize() && i < (end_line - 1);
126+
++i) {
127+
locations.emplace_back(i, 0);
132128
}
133129
}
134130

lldb/tools/lldb-dap/Handler/RequestHandler.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,15 @@ class SetBreakpointsRequestHandler
389389
}
390390
llvm::Expected<protocol::SetBreakpointsResponseBody>
391391
Run(const protocol::SetBreakpointsArguments &args) const override;
392+
393+
std::vector<protocol::Breakpoint> SetSourceBreakpoints(
394+
const std::string &path,
395+
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
396+
const;
397+
std::vector<protocol::Breakpoint> SetAssemblyBreakpoints(
398+
int64_t sourceReference,
399+
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
400+
const;
392401
};
393402

394403
class SetExceptionBreakpointsRequestHandler : public LegacyRequestHandler {

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

Lines changed: 86 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
#include "DAP.h"
1010
#include "EventHelper.h"
1111
#include "JSONUtils.h"
12+
#include "LLDBUtils.h"
1213
#include "Protocol/ProtocolRequests.h"
1314
#include "RequestHandler.h"
15+
#include <cstdint>
16+
#include <utility>
1417
#include <vector>
1518

1619
namespace lldb_dap {
@@ -23,15 +26,30 @@ llvm::Expected<protocol::SetBreakpointsResponseBody>
2326
SetBreakpointsRequestHandler::Run(
2427
const protocol::SetBreakpointsArguments &args) const {
2528
const auto &source = args.source;
26-
const auto path = source.path.value_or("");
29+
std::vector<protocol::Breakpoint> response_breakpoints;
30+
if (source.sourceReference)
31+
response_breakpoints = SetAssemblyBreakpoints(
32+
source.sourceReference.value(), args.breakpoints);
33+
else if (source.path)
34+
response_breakpoints =
35+
SetSourceBreakpoints(source.path.value(), args.breakpoints);
36+
37+
return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
38+
}
39+
40+
std::vector<protocol::Breakpoint>
41+
SetBreakpointsRequestHandler::SetSourceBreakpoints(
42+
const std::string &path,
43+
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
44+
const {
2745
std::vector<protocol::Breakpoint> response_breakpoints;
2846

2947
// Decode the source breakpoint infos for this "setBreakpoints" request
3048
SourceBreakpointMap request_bps;
3149
// "breakpoints" may be unset, in which case we treat it the same as being set
3250
// to an empty array.
33-
if (args.breakpoints) {
34-
for (const auto &bp : *args.breakpoints) {
51+
if (breakpoints) {
52+
for (const auto &bp : *breakpoints) {
3553
SourceBreakpoint src_bp(dap, bp);
3654
std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(),
3755
src_bp.GetColumn());
@@ -73,7 +91,71 @@ SetBreakpointsRequestHandler::Run(
7391
}
7492
}
7593

76-
return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
94+
return response_breakpoints;
95+
}
96+
97+
std::vector<protocol::Breakpoint>
98+
SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
99+
int64_t sourceReference,
100+
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
101+
const {
102+
std::vector<protocol::Breakpoint> response_breakpoints;
103+
104+
lldb::SBProcess process = dap.target.GetProcess();
105+
lldb::SBThread thread =
106+
process.GetThreadByIndexID(GetLLDBThreadIndexID(sourceReference));
107+
lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(sourceReference));
108+
109+
if (!frame.IsValid())
110+
return response_breakpoints;
111+
112+
lldb::SBSymbol symbol = frame.GetSymbol();
113+
if (!symbol.IsValid())
114+
return response_breakpoints; // Not yet supporting breakpoints in assembly
115+
// without a valid symbol
116+
117+
SourceBreakpointMap request_bps;
118+
if (breakpoints) {
119+
for (const auto &bp : *breakpoints) {
120+
SourceBreakpoint src_bp(dap, bp);
121+
std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(), 0);
122+
request_bps.try_emplace(bp_pos, src_bp);
123+
const auto [iv, inserted] =
124+
dap.assembly_breakpoints[sourceReference].try_emplace(bp_pos, src_bp);
125+
// We check if this breakpoint already exists to update it
126+
if (inserted)
127+
iv->getSecond().SetBreakpoint(symbol);
128+
else
129+
iv->getSecond().UpdateBreakpoint(src_bp);
130+
131+
protocol::Breakpoint response_bp = iv->getSecond().ToProtocolBreakpoint();
132+
protocol::Source source;
133+
source.sourceReference = sourceReference;
134+
source.name = symbol.GetName();
135+
response_bp.source = std::move(source);
136+
137+
if (!response_bp.line)
138+
response_bp.line = src_bp.GetLine();
139+
if (!response_bp.column)
140+
response_bp.column = src_bp.GetColumn();
141+
response_breakpoints.push_back(response_bp);
142+
}
143+
}
144+
145+
// Delete existing breakpoints for this sourceReference that are not in the
146+
// request_bps set.
147+
auto old_src_bp_pos = dap.assembly_breakpoints.find(sourceReference);
148+
if (old_src_bp_pos != dap.assembly_breakpoints.end()) {
149+
for (auto &old_bp : old_src_bp_pos->second) {
150+
auto request_pos = request_bps.find(old_bp.first);
151+
if (request_pos == request_bps.end()) {
152+
dap.target.BreakpointDelete(old_bp.second.GetID());
153+
old_src_bp_pos->second.erase(old_bp.first);
154+
}
155+
}
156+
}
157+
158+
return response_breakpoints;
77159
}
78160

79161
} // namespace lldb_dap

lldb/tools/lldb-dap/SourceBreakpoint.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include "lldb/API/SBBreakpoint.h"
1414
#include "lldb/API/SBFileSpecList.h"
1515
#include "lldb/API/SBFrame.h"
16+
#include "lldb/API/SBInstruction.h"
1617
#include "lldb/API/SBMutex.h"
18+
#include "lldb/API/SBSymbol.h"
1719
#include "lldb/API/SBTarget.h"
1820
#include "lldb/API/SBThread.h"
1921
#include "lldb/API/SBValue.h"
@@ -45,6 +47,26 @@ void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
4547
Breakpoint::SetBreakpoint();
4648
}
4749

50+
void SourceBreakpoint::SetBreakpoint(lldb::SBSymbol &symbol) {
51+
lldb::SBMutex lock = m_dap.GetAPIMutex();
52+
std::lock_guard<lldb::SBMutex> guard(lock);
53+
54+
if (m_line == 0)
55+
return;
56+
57+
lldb::SBInstructionList inst_list =
58+
m_dap.target.ReadInstructions(symbol.GetStartAddress(), m_line);
59+
if (inst_list.GetSize() < m_line)
60+
return;
61+
lldb::SBAddress address =
62+
inst_list.GetInstructionAtIndex(m_line - 1).GetAddress();
63+
64+
m_bp = m_dap.target.BreakpointCreateBySBAddress(address);
65+
if (!m_log_message.empty())
66+
SetLogMessage();
67+
Breakpoint::SetBreakpoint();
68+
}
69+
4870
void SourceBreakpoint::UpdateBreakpoint(const SourceBreakpoint &request_bp) {
4971
if (m_log_message != request_bp.m_log_message) {
5072
m_log_message = request_bp.m_log_message;

lldb/tools/lldb-dap/SourceBreakpoint.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class SourceBreakpoint : public Breakpoint {
2626

2727
// Set this breakpoint in LLDB as a new breakpoint
2828
void SetBreakpoint(const llvm::StringRef source_path);
29+
void SetBreakpoint(lldb::SBSymbol &symbol);
2930
void UpdateBreakpoint(const SourceBreakpoint &request_bp);
3031

3132
void SetLogMessage();

0 commit comments

Comments
 (0)