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
1619namespace lldb_dap {
@@ -23,15 +26,30 @@ llvm::Expected<protocol::SetBreakpointsResponseBody>
2326SetBreakpointsRequestHandler::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
0 commit comments