[Lldb-commits] [lldb] [lldb-dap] assembly breakpoints (PR #139969)
Ely Ronnen via lldb-commits
lldb-commits at lists.llvm.org
Sun May 18 05:06:56 PDT 2025
https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/139969
>From d6325b3f6a8602fc96ad72acecfcccda1120614d Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 10 May 2025 20:45:17 +0200
Subject: [PATCH 01/14] support assembly in BreakpointLocationsRequestHandler
---
.../breakpoint/TestDAP_setBreakpoints.py | 1 -
.../TestDAP_setExceptionBreakpoints.py | 1 -
.../TestDAP_setFunctionBreakpoints.py | 1 -
lldb/tools/lldb-dap/DAP.h | 3 +
.../Handler/BreakpointLocationsHandler.cpp | 77 +++++++++++++++----
lldb/tools/lldb-dap/Handler/RequestHandler.h | 11 +++
.../lldb-dap/Handler/SourceRequestHandler.cpp | 4 +-
7 files changed, 76 insertions(+), 22 deletions(-)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
index aae1251b17c93..26df2573555df 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
@@ -12,7 +12,6 @@
import os
- at skip("Temporarily disable the breakpoint tests")
class TestDAP_setBreakpoints(lldbdap_testcase.DAPTestCaseBase):
def setUp(self):
lldbdap_testcase.DAPTestCaseBase.setUp(self)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
index 4dc8c5b3c7ded..92ac66cd44c5d 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
@@ -10,7 +10,6 @@
import lldbdap_testcase
- at skip("Temporarily disable the breakpoint tests")
class TestDAP_setExceptionBreakpoints(lldbdap_testcase.DAPTestCaseBase):
@skipIfWindows
def test_functionality(self):
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
index baaca4d974d5d..946595f639edc 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
@@ -10,7 +10,6 @@
import lldbdap_testcase
- at skip("Temporarily disable the breakpoint tests")
class TestDAP_setFunctionBreakpoints(lldbdap_testcase.DAPTestCaseBase):
@skipIfWindows
def test_set_and_clear(self):
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 8f24c6cf82924..00aa4276852c5 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -219,6 +219,9 @@ struct DAP {
llvm::StringSet<> modules;
/// @}
+ /// Number of lines of assembly code to show when no debug info is available.
+ uint32_t number_of_assembly_lines_for_nodebug = 32;
+
/// Creates a new DAP sessions.
///
/// \param[in] log
diff --git a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
index 2ac886c3a5d2c..9eea549d72b00 100644
--- a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "DAP.h"
-#include "JSONUtils.h"
+#include "LLDBUtils.h"
#include "RequestHandler.h"
#include <vector>
@@ -19,19 +19,50 @@ namespace lldb_dap {
llvm::Expected<protocol::BreakpointLocationsResponseBody>
BreakpointLocationsRequestHandler::Run(
const protocol::BreakpointLocationsArguments &args) const {
- std::string path = args.source.path.value_or("");
uint32_t start_line = args.line;
uint32_t start_column = args.column.value_or(LLDB_INVALID_COLUMN_NUMBER);
uint32_t end_line = args.endLine.value_or(start_line);
uint32_t end_column =
args.endColumn.value_or(std::numeric_limits<uint32_t>::max());
+ // Find all relevant lines & columns
+ llvm::SmallVector<std::pair<uint32_t, uint32_t>, 8> locations;
+ if (args.source.sourceReference) {
+ AddAssemblyBreakpointLocations(locations, *args.source.sourceReference,
+ start_line, end_line);
+ } else {
+ std::string path = args.source.path.value_or("");
+ AddSourceBreakpointLocations(locations, std::move(path), start_line,
+ start_column, end_line, end_column);
+ }
+
+ // The line entries are sorted by addresses, but we must return the list
+ // ordered by line / column position.
+ std::sort(locations.begin(), locations.end());
+ locations.erase(llvm::unique(locations), locations.end());
+
+ std::vector<protocol::BreakpointLocation> breakpoint_locations;
+ for (auto &l : locations) {
+ protocol::BreakpointLocation lc;
+ lc.line = l.first;
+ lc.column = l.second;
+ breakpoint_locations.push_back(std::move(lc));
+ }
+
+ return protocol::BreakpointLocationsResponseBody{
+ /*breakpoints=*/std::move(breakpoint_locations)};
+}
+
+template <unsigned N>
+void BreakpointLocationsRequestHandler::AddSourceBreakpointLocations(
+ llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
+ std::string path, uint32_t start_line, uint32_t start_column,
+ uint32_t end_line, uint32_t end_column) const {
+
lldb::SBFileSpec file_spec(path.c_str(), true);
lldb::SBSymbolContextList compile_units =
dap.target.FindCompileUnits(file_spec);
- // Find all relevant lines & columns
- llvm::SmallVector<std::pair<uint32_t, uint32_t>, 8> locations;
for (uint32_t c_idx = 0, c_limit = compile_units.GetSize(); c_idx < c_limit;
++c_idx) {
const lldb::SBCompileUnit &compile_unit =
@@ -71,22 +102,34 @@ BreakpointLocationsRequestHandler::Run(
locations.emplace_back(line, column);
}
}
+}
- // The line entries are sorted by addresses, but we must return the list
- // ordered by line / column position.
- std::sort(locations.begin(), locations.end());
- locations.erase(llvm::unique(locations), locations.end());
+template <unsigned N>
+void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
+ llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
+ int64_t sourceReference, uint32_t start_line, uint32_t end_line) const {
+ lldb::SBProcess process = dap.target.GetProcess();
+ lldb::SBThread thread =
+ process.GetThreadByIndexID(GetLLDBThreadIndexID(sourceReference));
+ lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(sourceReference));
- std::vector<protocol::BreakpointLocation> breakpoint_locations;
- for (auto &l : locations) {
- protocol::BreakpointLocation lc;
- lc.line = l.first;
- lc.column = l.second;
- breakpoint_locations.push_back(std::move(lc));
- }
+ if (!frame.IsValid())
+ return;
- return protocol::BreakpointLocationsResponseBody{
- /*breakpoints=*/std::move(breakpoint_locations)};
+ lldb::SBSymbol symbol = frame.GetSymbol();
+ if (symbol.IsValid()) {
+ lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
+ for (uint32_t i = start_line - 1; i < insts.GetSize() && i < (end_line - 1);
+ ++i) {
+ locations.emplace_back(i, 0);
+ }
+ } else {
+ for (uint32_t i = start_line - 1;
+ i < dap.number_of_assembly_lines_for_nodebug && i < (end_line - 1);
+ ++i) {
+ locations.emplace_back(i, 0);
+ }
+ }
}
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index e6bccfe12f402..21753bc0552f9 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -16,6 +16,7 @@
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
@@ -232,6 +233,16 @@ class BreakpointLocationsRequestHandler
}
llvm::Expected<protocol::BreakpointLocationsResponseBody>
Run(const protocol::BreakpointLocationsArguments &args) const override;
+
+ template <unsigned N>
+ void AddSourceBreakpointLocations(
+ llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
+ std::string path, uint32_t start_line, uint32_t start_column,
+ uint32_t end_line, uint32_t end_column) const;
+ template <unsigned N>
+ void AddAssemblyBreakpointLocations(
+ llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
+ int64_t sourceReference, uint32_t start_line, uint32_t end_line) const;
};
class CompletionsRequestHandler : public LegacyRequestHandler {
diff --git a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
index 0ddd87881a164..fb396a3dc8862 100644
--- a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
@@ -52,8 +52,8 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
insts.GetDescription(stream, exe_ctx);
} else {
// No valid symbol, just return the disassembly.
- lldb::SBInstructionList insts =
- dap.target.ReadInstructions(frame.GetPCAddress(), 32);
+ lldb::SBInstructionList insts = dap.target.ReadInstructions(
+ frame.GetPCAddress(), dap.number_of_assembly_lines_for_nodebug);
insts.GetDescription(stream, exe_ctx);
}
>From ee492031bee8106fb2a4ff22a8563005f5afd86c Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 11 May 2025 19:49:03 +0200
Subject: [PATCH 02/14] support assembly in SetBreakpointsRequestHandler
---
lldb/tools/lldb-dap/DAP.h | 1 +
.../Handler/BreakpointLocationsHandler.cpp | 20 ++---
lldb/tools/lldb-dap/Handler/RequestHandler.h | 9 ++
.../Handler/SetBreakpointsRequestHandler.cpp | 90 ++++++++++++++++++-
lldb/tools/lldb-dap/SourceBreakpoint.cpp | 22 +++++
lldb/tools/lldb-dap/SourceBreakpoint.h | 1 +
6 files changed, 127 insertions(+), 16 deletions(-)
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 00aa4276852c5..5ce0e534611c1 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -169,6 +169,7 @@ struct DAP {
Variables variables;
lldb::SBBroadcaster broadcaster;
llvm::StringMap<SourceBreakpointMap> source_breakpoints;
+ llvm::DenseMap<int64_t, SourceBreakpointMap> assembly_breakpoints;
FunctionBreakpointMap function_breakpoints;
InstructionBreakpointMap instruction_breakpoints;
std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;
diff --git a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
index 9eea549d72b00..be02c47056310 100644
--- a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
@@ -117,18 +117,14 @@ void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
return;
lldb::SBSymbol symbol = frame.GetSymbol();
- if (symbol.IsValid()) {
- lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
- for (uint32_t i = start_line - 1; i < insts.GetSize() && i < (end_line - 1);
- ++i) {
- locations.emplace_back(i, 0);
- }
- } else {
- for (uint32_t i = start_line - 1;
- i < dap.number_of_assembly_lines_for_nodebug && i < (end_line - 1);
- ++i) {
- locations.emplace_back(i, 0);
- }
+ if (!symbol.IsValid())
+ return;
+
+ // start_line is relative to the symbol's start address
+ lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
+ for (uint32_t i = start_line - 1; i < insts.GetSize() && i < (end_line - 1);
+ ++i) {
+ locations.emplace_back(i, 0);
}
}
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 21753bc0552f9..72843aaef8150 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -389,6 +389,15 @@ class SetBreakpointsRequestHandler
}
llvm::Expected<protocol::SetBreakpointsResponseBody>
Run(const protocol::SetBreakpointsArguments &args) const override;
+
+ std::vector<protocol::Breakpoint> SetSourceBreakpoints(
+ const std::string &path,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
+ const;
+ std::vector<protocol::Breakpoint> SetAssemblyBreakpoints(
+ int64_t sourceReference,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
+ const;
};
class SetExceptionBreakpointsRequestHandler : public LegacyRequestHandler {
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
index 86e090b66afe9..71f9e5578ef08 100644
--- a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -9,8 +9,11 @@
#include "DAP.h"
#include "EventHelper.h"
#include "JSONUtils.h"
+#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "RequestHandler.h"
+#include <cstdint>
+#include <utility>
#include <vector>
namespace lldb_dap {
@@ -23,15 +26,30 @@ llvm::Expected<protocol::SetBreakpointsResponseBody>
SetBreakpointsRequestHandler::Run(
const protocol::SetBreakpointsArguments &args) const {
const auto &source = args.source;
- const auto path = source.path.value_or("");
+ std::vector<protocol::Breakpoint> response_breakpoints;
+ if (source.sourceReference)
+ response_breakpoints = SetAssemblyBreakpoints(
+ source.sourceReference.value(), args.breakpoints);
+ else if (source.path)
+ response_breakpoints =
+ SetSourceBreakpoints(source.path.value(), args.breakpoints);
+
+ return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
+}
+
+std::vector<protocol::Breakpoint>
+SetBreakpointsRequestHandler::SetSourceBreakpoints(
+ const std::string &path,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
+ const {
std::vector<protocol::Breakpoint> response_breakpoints;
// Decode the source breakpoint infos for this "setBreakpoints" request
SourceBreakpointMap request_bps;
// "breakpoints" may be unset, in which case we treat it the same as being set
// to an empty array.
- if (args.breakpoints) {
- for (const auto &bp : *args.breakpoints) {
+ if (breakpoints) {
+ for (const auto &bp : *breakpoints) {
SourceBreakpoint src_bp(dap, bp);
std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(),
src_bp.GetColumn());
@@ -73,7 +91,71 @@ SetBreakpointsRequestHandler::Run(
}
}
- return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
+ return response_breakpoints;
+}
+
+std::vector<protocol::Breakpoint>
+SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
+ int64_t sourceReference,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
+ const {
+ std::vector<protocol::Breakpoint> response_breakpoints;
+
+ lldb::SBProcess process = dap.target.GetProcess();
+ lldb::SBThread thread =
+ process.GetThreadByIndexID(GetLLDBThreadIndexID(sourceReference));
+ lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(sourceReference));
+
+ if (!frame.IsValid())
+ return response_breakpoints;
+
+ lldb::SBSymbol symbol = frame.GetSymbol();
+ if (!symbol.IsValid())
+ return response_breakpoints; // Not yet supporting breakpoints in assembly
+ // without a valid symbol
+
+ SourceBreakpointMap request_bps;
+ if (breakpoints) {
+ for (const auto &bp : *breakpoints) {
+ SourceBreakpoint src_bp(dap, bp);
+ std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(), 0);
+ request_bps.try_emplace(bp_pos, src_bp);
+ const auto [iv, inserted] =
+ dap.assembly_breakpoints[sourceReference].try_emplace(bp_pos, src_bp);
+ // We check if this breakpoint already exists to update it
+ if (inserted)
+ iv->getSecond().SetBreakpoint(symbol);
+ else
+ iv->getSecond().UpdateBreakpoint(src_bp);
+
+ protocol::Breakpoint response_bp = iv->getSecond().ToProtocolBreakpoint();
+ protocol::Source source;
+ source.sourceReference = sourceReference;
+ source.name = symbol.GetName();
+ response_bp.source = std::move(source);
+
+ if (!response_bp.line)
+ response_bp.line = src_bp.GetLine();
+ if (!response_bp.column)
+ response_bp.column = src_bp.GetColumn();
+ response_breakpoints.push_back(response_bp);
+ }
+ }
+
+ // Delete existing breakpoints for this sourceReference that are not in the
+ // request_bps set.
+ auto old_src_bp_pos = dap.assembly_breakpoints.find(sourceReference);
+ if (old_src_bp_pos != dap.assembly_breakpoints.end()) {
+ for (auto &old_bp : old_src_bp_pos->second) {
+ auto request_pos = request_bps.find(old_bp.first);
+ if (request_pos == request_bps.end()) {
+ dap.target.BreakpointDelete(old_bp.second.GetID());
+ old_src_bp_pos->second.erase(old_bp.first);
+ }
+ }
+ }
+
+ return response_breakpoints;
}
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index 4581c995b4260..938b8fb8bcdda 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -13,7 +13,9 @@
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBFileSpecList.h"
#include "lldb/API/SBFrame.h"
+#include "lldb/API/SBInstruction.h"
#include "lldb/API/SBMutex.h"
+#include "lldb/API/SBSymbol.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBValue.h"
@@ -45,6 +47,26 @@ void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
Breakpoint::SetBreakpoint();
}
+void SourceBreakpoint::SetBreakpoint(lldb::SBSymbol &symbol) {
+ lldb::SBMutex lock = m_dap.GetAPIMutex();
+ std::lock_guard<lldb::SBMutex> guard(lock);
+
+ if (m_line == 0)
+ return;
+
+ lldb::SBInstructionList inst_list =
+ m_dap.target.ReadInstructions(symbol.GetStartAddress(), m_line);
+ if (inst_list.GetSize() < m_line)
+ return;
+ lldb::SBAddress address =
+ inst_list.GetInstructionAtIndex(m_line - 1).GetAddress();
+
+ m_bp = m_dap.target.BreakpointCreateBySBAddress(address);
+ if (!m_log_message.empty())
+ SetLogMessage();
+ Breakpoint::SetBreakpoint();
+}
+
void SourceBreakpoint::UpdateBreakpoint(const SourceBreakpoint &request_bp) {
if (m_log_message != request_bp.m_log_message) {
m_log_message = request_bp.m_log_message;
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h
index 5b15296f861c5..8589800e50983 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.h
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.h
@@ -26,6 +26,7 @@ class SourceBreakpoint : public Breakpoint {
// Set this breakpoint in LLDB as a new breakpoint
void SetBreakpoint(const llvm::StringRef source_path);
+ void SetBreakpoint(lldb::SBSymbol &symbol);
void UpdateBreakpoint(const SourceBreakpoint &request_bp);
void SetLogMessage();
>From dbb2f9bd55b3f86247e03b2610fca9576e124637 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Wed, 14 May 2025 23:51:41 +0200
Subject: [PATCH 03/14] fix resolving of assembly source breakpoints
---
lldb/tools/lldb-dap/Breakpoint.cpp | 45 ++++++++++++++++---
lldb/tools/lldb-dap/DAP.h | 3 +-
.../Handler/BreakpointLocationsHandler.cpp | 4 +-
lldb/tools/lldb-dap/Handler/RequestHandler.h | 4 +-
.../Handler/SetBreakpointsRequestHandler.cpp | 30 ++++++-------
lldb/tools/lldb-dap/package-lock.json | 4 +-
lldb/tools/lldb-dap/package.json | 5 ++-
7 files changed, 63 insertions(+), 32 deletions(-)
diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp
index 26d633d1d172e..87fcd15b0a568 100644
--- a/lldb/tools/lldb-dap/Breakpoint.cpp
+++ b/lldb/tools/lldb-dap/Breakpoint.cpp
@@ -9,10 +9,12 @@
#include "Breakpoint.h"
#include "DAP.h"
#include "JSONUtils.h"
+#include "LLDBUtils.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBBreakpointLocation.h"
#include "lldb/API/SBLineEntry.h"
#include "lldb/API/SBMutex.h"
+#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/StringExtras.h"
#include <cstddef>
#include <cstdint>
@@ -63,14 +65,43 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() {
std::string formatted_addr =
"0x" + llvm::utohexstr(bp_addr.GetLoadAddress(m_bp.GetTarget()));
breakpoint.instructionReference = formatted_addr;
+
+ lldb::StopDisassemblyType stop_disassembly_display =
+ GetStopDisassemblyDisplay(m_dap.debugger);
auto line_entry = bp_addr.GetLineEntry();
- const auto line = line_entry.GetLine();
- if (line != UINT32_MAX)
- breakpoint.line = line;
- const auto column = line_entry.GetColumn();
- if (column != 0)
- breakpoint.column = column;
- breakpoint.source = CreateSource(line_entry);
+ if (!ShouldDisplayAssemblySource(line_entry, stop_disassembly_display)) {
+ const auto line = line_entry.GetLine();
+ if (line != UINT32_MAX)
+ breakpoint.line = line;
+ const auto column = line_entry.GetColumn();
+ if (column != 0)
+ breakpoint.column = column;
+ breakpoint.source = CreateSource(line_entry);
+ } else {
+ // Breakpoint made by assembly
+ auto symbol_context = bp_addr.GetSymbolContext(
+ lldb::eSymbolContextSymbol | lldb::eSymbolContextModule);
+ if (symbol_context.IsValid()) {
+ auto symbol = symbol_context.GetSymbol();
+ breakpoint.line =
+ m_bp.GetTarget()
+ .ReadInstructions(symbol.GetStartAddress(), bp_addr, nullptr)
+ .GetSize() +
+ 1;
+ protocol::Source source;
+ source.name = symbol.GetName();
+
+ auto module = symbol_context.GetModule();
+ if (module.IsValid()) {
+ std::string path = module.GetFileSpec().GetDirectory();
+ path += "/";
+ path += module.GetFileSpec().GetFilename();
+ source.path = std::move(path);
+ }
+
+ breakpoint.source = std::move(source);
+ }
+ }
}
return breakpoint;
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 5ce0e534611c1..b0fe265b7bca1 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -169,7 +169,8 @@ struct DAP {
Variables variables;
lldb::SBBroadcaster broadcaster;
llvm::StringMap<SourceBreakpointMap> source_breakpoints;
- llvm::DenseMap<int64_t, SourceBreakpointMap> assembly_breakpoints;
+ llvm::DenseMap<int64_t, llvm::DenseMap<uint32_t, SourceBreakpoint>>
+ assembly_breakpoints;
FunctionBreakpointMap function_breakpoints;
InstructionBreakpointMap instruction_breakpoints;
std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;
diff --git a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
index be02c47056310..06ada47a6f27f 100644
--- a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
@@ -122,9 +122,9 @@ void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
// start_line is relative to the symbol's start address
lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
- for (uint32_t i = start_line - 1; i < insts.GetSize() && i < (end_line - 1);
+ for (uint32_t i = start_line - 1; i < insts.GetSize() && i <= (end_line - 1);
++i) {
- locations.emplace_back(i, 0);
+ locations.emplace_back(i, 1);
}
}
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 72843aaef8150..80898d1ee5ef1 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -391,11 +391,11 @@ class SetBreakpointsRequestHandler
Run(const protocol::SetBreakpointsArguments &args) const override;
std::vector<protocol::Breakpoint> SetSourceBreakpoints(
- const std::string &path,
+ const protocol::Source &source,
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
const;
std::vector<protocol::Breakpoint> SetAssemblyBreakpoints(
- int64_t sourceReference,
+ const protocol::Source &source,
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
const;
};
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
index 71f9e5578ef08..4fefd8b440c7d 100644
--- a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -28,21 +28,20 @@ SetBreakpointsRequestHandler::Run(
const auto &source = args.source;
std::vector<protocol::Breakpoint> response_breakpoints;
if (source.sourceReference)
- response_breakpoints = SetAssemblyBreakpoints(
- source.sourceReference.value(), args.breakpoints);
+ response_breakpoints = SetAssemblyBreakpoints(source, args.breakpoints);
else if (source.path)
- response_breakpoints =
- SetSourceBreakpoints(source.path.value(), args.breakpoints);
+ response_breakpoints = SetSourceBreakpoints(source, args.breakpoints);
return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
}
std::vector<protocol::Breakpoint>
SetBreakpointsRequestHandler::SetSourceBreakpoints(
- const std::string &path,
+ const protocol::Source &source,
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
const {
std::vector<protocol::Breakpoint> response_breakpoints;
+ std::string path = source.path.value_or("");
// Decode the source breakpoint infos for this "setBreakpoints" request
SourceBreakpointMap request_bps;
@@ -96,10 +95,11 @@ SetBreakpointsRequestHandler::SetSourceBreakpoints(
std::vector<protocol::Breakpoint>
SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
- int64_t sourceReference,
+ const protocol::Source &source,
const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
const {
std::vector<protocol::Breakpoint> response_breakpoints;
+ int64_t sourceReference = source.sourceReference.value_or(0);
lldb::SBProcess process = dap.target.GetProcess();
lldb::SBThread thread =
@@ -114,14 +114,14 @@ SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
return response_breakpoints; // Not yet supporting breakpoints in assembly
// without a valid symbol
- SourceBreakpointMap request_bps;
+ llvm::DenseMap<uint32_t, SourceBreakpoint> request_bps;
if (breakpoints) {
for (const auto &bp : *breakpoints) {
SourceBreakpoint src_bp(dap, bp);
- std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(), 0);
- request_bps.try_emplace(bp_pos, src_bp);
+ request_bps.try_emplace(src_bp.GetLine(), src_bp);
const auto [iv, inserted] =
- dap.assembly_breakpoints[sourceReference].try_emplace(bp_pos, src_bp);
+ dap.assembly_breakpoints[sourceReference].try_emplace(
+ src_bp.GetLine(), src_bp);
// We check if this breakpoint already exists to update it
if (inserted)
iv->getSecond().SetBreakpoint(symbol);
@@ -129,15 +129,11 @@ SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
iv->getSecond().UpdateBreakpoint(src_bp);
protocol::Breakpoint response_bp = iv->getSecond().ToProtocolBreakpoint();
- protocol::Source source;
- source.sourceReference = sourceReference;
- source.name = symbol.GetName();
- response_bp.source = std::move(source);
-
+ response_bp.source = source;
if (!response_bp.line)
response_bp.line = src_bp.GetLine();
- if (!response_bp.column)
- response_bp.column = src_bp.GetColumn();
+ if (bp.column)
+ response_bp.column = *bp.column;
response_breakpoints.push_back(response_bp);
}
}
diff --git a/lldb/tools/lldb-dap/package-lock.json b/lldb/tools/lldb-dap/package-lock.json
index 0a2b9e764067e..af90a9573aee6 100644
--- a/lldb/tools/lldb-dap/package-lock.json
+++ b/lldb/tools/lldb-dap/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "lldb-dap",
- "version": "0.2.13",
+ "version": "0.2.14",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "lldb-dap",
- "version": "0.2.13",
+ "version": "0.2.14",
"license": "Apache 2.0 License with LLVM exceptions",
"devDependencies": {
"@types/node": "^18.19.41",
diff --git a/lldb/tools/lldb-dap/package.json b/lldb/tools/lldb-dap/package.json
index d5ca604798799..73e70cd961f4f 100644
--- a/lldb/tools/lldb-dap/package.json
+++ b/lldb/tools/lldb-dap/package.json
@@ -1,7 +1,7 @@
{
"name": "lldb-dap",
"displayName": "LLDB DAP",
- "version": "0.2.13",
+ "version": "0.2.14",
"publisher": "llvm-vs-code-extensions",
"homepage": "https://lldb.llvm.org",
"description": "Debugging with LLDB in Visual Studio Code",
@@ -265,6 +265,9 @@
]
},
"breakpoints": [
+ {
+ "language": "lldb.disassembly"
+ },
{
"language": "ada"
},
>From 3699524618ed76f969cc26a63610fe54e3605139 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Thu, 15 May 2025 00:36:10 +0200
Subject: [PATCH 04/14] remove include
---
lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
index 4fefd8b440c7d..d69da5bd02c1e 100644
--- a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -12,8 +12,6 @@
#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "RequestHandler.h"
-#include <cstdint>
-#include <utility>
#include <vector>
namespace lldb_dap {
>From 61623deb7e249a8ca0c63e3f66955790da5e4ced Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 17 May 2025 21:05:27 +0200
Subject: [PATCH 05/14] use load address as sourceReference
---
lldb/include/lldb/API/SBFileSpec.h | 3 +
lldb/source/API/SBFileSpec.cpp | 8 ++
lldb/tools/lldb-dap/Breakpoint.cpp | 18 +----
.../Handler/BreakpointLocationsHandler.cpp | 11 +--
.../Handler/SetBreakpointsRequestHandler.cpp | 11 +--
.../lldb-dap/Handler/SourceRequestHandler.cpp | 18 ++---
lldb/tools/lldb-dap/JSONUtils.cpp | 75 +++++++++++++------
lldb/tools/lldb-dap/JSONUtils.h | 14 ++++
8 files changed, 96 insertions(+), 62 deletions(-)
diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h
index 36641843aabeb..303cb7d712cbf 100644
--- a/lldb/include/lldb/API/SBFileSpec.h
+++ b/lldb/include/lldb/API/SBFileSpec.h
@@ -10,6 +10,7 @@
#define LLDB_API_SBFILESPEC_H
#include "lldb/API/SBDefines.h"
+#include "lldb/API/SBStream.h"
namespace lldb {
@@ -53,6 +54,8 @@ class LLDB_API SBFileSpec {
uint32_t GetPath(char *dst_path, size_t dst_len) const;
+ bool GetPath(lldb::SBStream &dst_path) const;
+
static int ResolvePath(const char *src_path, char *dst_path, size_t dst_len);
bool GetDescription(lldb::SBStream &description) const;
diff --git a/lldb/source/API/SBFileSpec.cpp b/lldb/source/API/SBFileSpec.cpp
index a7df9afc4b8eb..cb44dac1d4fcc 100644
--- a/lldb/source/API/SBFileSpec.cpp
+++ b/lldb/source/API/SBFileSpec.cpp
@@ -19,6 +19,7 @@
#include <cinttypes>
#include <climits>
+#include <string>
using namespace lldb;
using namespace lldb_private;
@@ -147,6 +148,13 @@ uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const {
return result;
}
+bool SBFileSpec::GetPath(SBStream &dst_path) const {
+ LLDB_INSTRUMENT_VA(this, dst_path);
+
+ std::string path = m_opaque_up->GetPath();
+ return dst_path->PutCString(path.c_str()) > 0;
+}
+
const lldb_private::FileSpec *SBFileSpec::operator->() const {
return m_opaque_up.get();
}
diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp
index 87fcd15b0a568..a54a34e0f936d 100644
--- a/lldb/tools/lldb-dap/Breakpoint.cpp
+++ b/lldb/tools/lldb-dap/Breakpoint.cpp
@@ -79,27 +79,15 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() {
breakpoint.source = CreateSource(line_entry);
} else {
// Breakpoint made by assembly
- auto symbol_context = bp_addr.GetSymbolContext(
- lldb::eSymbolContextSymbol | lldb::eSymbolContextModule);
- if (symbol_context.IsValid()) {
- auto symbol = symbol_context.GetSymbol();
+ auto symbol = bp_addr.GetSymbol();
+ if (symbol.IsValid()) {
breakpoint.line =
m_bp.GetTarget()
.ReadInstructions(symbol.GetStartAddress(), bp_addr, nullptr)
.GetSize() +
1;
- protocol::Source source;
- source.name = symbol.GetName();
- auto module = symbol_context.GetModule();
- if (module.IsValid()) {
- std::string path = module.GetFileSpec().GetDirectory();
- path += "/";
- path += module.GetFileSpec().GetFilename();
- source.path = std::move(path);
- }
-
- breakpoint.source = std::move(source);
+ breakpoint.source = CreateAssemblySource(m_dap.target, bp_addr);
}
}
}
diff --git a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
index 06ada47a6f27f..c4d658caeee2d 100644
--- a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "DAP.h"
-#include "LLDBUtils.h"
#include "RequestHandler.h"
#include <vector>
@@ -108,15 +107,11 @@ template <unsigned N>
void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
int64_t sourceReference, uint32_t start_line, uint32_t end_line) const {
- lldb::SBProcess process = dap.target.GetProcess();
- lldb::SBThread thread =
- process.GetThreadByIndexID(GetLLDBThreadIndexID(sourceReference));
- lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(sourceReference));
-
- if (!frame.IsValid())
+ lldb::SBAddress address(sourceReference, dap.target);
+ if (!address.IsValid())
return;
- lldb::SBSymbol symbol = frame.GetSymbol();
+ lldb::SBSymbol symbol = address.GetSymbol();
if (!symbol.IsValid())
return;
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
index d69da5bd02c1e..7b401f06e9a85 100644
--- a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -9,7 +9,6 @@
#include "DAP.h"
#include "EventHelper.h"
#include "JSONUtils.h"
-#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "RequestHandler.h"
#include <vector>
@@ -99,15 +98,11 @@ SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
std::vector<protocol::Breakpoint> response_breakpoints;
int64_t sourceReference = source.sourceReference.value_or(0);
- lldb::SBProcess process = dap.target.GetProcess();
- lldb::SBThread thread =
- process.GetThreadByIndexID(GetLLDBThreadIndexID(sourceReference));
- lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(sourceReference));
-
- if (!frame.IsValid())
+ lldb::SBAddress address(sourceReference, dap.target);
+ if (!address.IsValid())
return response_breakpoints;
- lldb::SBSymbol symbol = frame.GetSymbol();
+ lldb::SBSymbol symbol = address.GetSymbol();
if (!symbol.IsValid())
return response_breakpoints; // Not yet supporting breakpoints in assembly
// without a valid symbol
diff --git a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
index fb396a3dc8862..9249e2aa6fef7 100644
--- a/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
@@ -11,6 +11,7 @@
#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
+#include "lldb/API/SBAddress.h"
#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBInstructionList.h"
@@ -19,6 +20,7 @@
#include "lldb/API/SBSymbol.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
+#include "lldb/lldb-types.h"
#include "llvm/Support/Error.h"
namespace lldb_dap {
@@ -34,18 +36,14 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
return llvm::make_error<DAPError>(
"invalid arguments, expected source.sourceReference to be set");
- lldb::SBProcess process = dap.target.GetProcess();
- // Upper 32 bits is the thread index ID
- lldb::SBThread thread =
- process.GetThreadByIndexID(GetLLDBThreadIndexID(source));
- // Lower 32 bits is the frame index
- lldb::SBFrame frame = thread.GetFrameAtIndex(GetLLDBFrameID(source));
- if (!frame.IsValid())
+ lldb::SBAddress address(source, dap.target);
+ if (!address.IsValid())
return llvm::make_error<DAPError>("source not found");
+ lldb::SBSymbol symbol = address.GetSymbol();
+
lldb::SBStream stream;
- lldb::SBExecutionContext exe_ctx(frame);
- lldb::SBSymbol symbol = frame.GetSymbol();
+ lldb::SBExecutionContext exe_ctx(dap.target);
if (symbol.IsValid()) {
lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
@@ -53,7 +51,7 @@ SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
} else {
// No valid symbol, just return the disassembly.
lldb::SBInstructionList insts = dap.target.ReadInstructions(
- frame.GetPCAddress(), dap.number_of_assembly_lines_for_nodebug);
+ address, dap.number_of_assembly_lines_for_nodebug);
insts.GetDescription(stream, exe_ctx);
}
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 714947a4d3b9c..c8151c3d64ea4 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -490,6 +490,13 @@ CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp) {
return filter;
}
+static std::string GetLoadAddressString(const lldb::addr_t addr) {
+ std::string result;
+ llvm::raw_string_ostream os(result);
+ os << llvm::format_hex(addr, 18);
+ return result;
+}
+
protocol::Source CreateSource(const lldb::SBFileSpec &file) {
protocol::Source source;
if (file.IsValid()) {
@@ -516,6 +523,43 @@ protocol::Source CreateSource(llvm::StringRef source_path) {
return source;
}
+protocol::Source CreateAssemblySource(const lldb::SBTarget &target,
+ lldb::SBAddress &address) {
+ protocol::Source source;
+
+ auto symbol = address.GetSymbol();
+ std::string name;
+ if (symbol.IsValid()) {
+ source.sourceReference = symbol.GetStartAddress().GetLoadAddress(target);
+ name = symbol.GetName();
+ } else {
+ const auto load_addr = address.GetLoadAddress(target);
+ source.sourceReference = load_addr;
+ name = GetLoadAddressString(load_addr);
+ }
+
+ lldb::SBModule module = address.GetModule();
+ if (module.IsValid()) {
+ lldb::SBFileSpec file_spec = module.GetFileSpec();
+ if (file_spec.IsValid()) {
+ lldb::SBStream module_path;
+ if (file_spec.GetPath(module_path)) {
+ std::string path = module_path.GetData();
+ source.path = path + '`' + name;
+ }
+ }
+ }
+
+ source.name = std::move(name);
+
+ // Mark the source as deemphasized since users will only be able to view
+ // assembly for these frames.
+ source.presentationHint =
+ protocol::Source::PresentationHint::eSourcePresentationHintDeemphasize;
+
+ return source;
+}
+
bool ShouldDisplayAssemblySource(
const lldb::SBLineEntry &line_entry,
lldb::StopDisassemblyType stop_disassembly_display) {
@@ -619,12 +663,10 @@ CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format,
frame_name = name;
}
- if (frame_name.empty()) {
+ if (frame_name.empty())
// If the function name is unavailable, display the pc address as a 16-digit
// hex string, e.g. "0x0000000000012345"
- llvm::raw_string_ostream os(frame_name);
- os << llvm::format_hex(frame.GetPC(), 18);
- }
+ frame_name = GetLoadAddressString(frame.GetPC());
// We only include `[opt]` if a custom frame format is not specified.
if (!format && frame.GetFunction().GetIsOptimized())
@@ -641,17 +683,10 @@ CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format,
} else if (frame.GetSymbol().IsValid()) {
// If no source is associated with the frame, use the DAPFrameID to track
// the 'source' and generate assembly.
- llvm::json::Object source;
- EmplaceSafeString(source, "name", frame_name);
- char buf[PATH_MAX] = {0};
- size_t size = frame.GetModule().GetFileSpec().GetPath(buf, PATH_MAX);
- EmplaceSafeString(source, "path",
- std::string(buf, size) + '`' + frame_name);
- source.try_emplace("sourceReference", MakeDAPFrameID(frame));
- // Mark the source as deemphasized since users will only be able to view
- // assembly for these frames.
- EmplaceSafeString(source, "presentationHint", "deemphasize");
- object.try_emplace("source", std::move(source));
+ auto frame_address = frame.GetPCAddress();
+ object.try_emplace("source", CreateAssemblySource(
+ frame.GetThread().GetProcess().GetTarget(),
+ frame_address));
// Calculate the line of the current PC from the start of the current
// symbol.
@@ -665,12 +700,10 @@ CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format,
object.try_emplace("column", 1);
} else {
// No valid line entry or symbol.
- llvm::json::Object source;
- EmplaceSafeString(source, "name", frame_name);
- source.try_emplace("sourceReference", MakeDAPFrameID(frame));
- EmplaceSafeString(source, "presentationHint", "deemphasize");
- object.try_emplace("source", std::move(source));
-
+ auto frame_address = frame.GetPCAddress();
+ object.try_emplace("source", CreateAssemblySource(
+ frame.GetThread().GetProcess().GetTarget(),
+ frame_address));
object.try_emplace("line", 1);
object.try_emplace("column", 1);
}
diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h
index 783f291338d8c..ac9b39739104f 100644
--- a/lldb/tools/lldb-dap/JSONUtils.h
+++ b/lldb/tools/lldb-dap/JSONUtils.h
@@ -269,6 +269,20 @@ protocol::Source CreateSource(const lldb::SBLineEntry &line_entry);
/// definition outlined by Microsoft.
protocol::Source CreateSource(llvm::StringRef source_path);
+/// Create a "Source" object for a given frame, using its assembly for source.
+///
+/// \param[in] target
+/// The relevant target.
+///
+/// \param[in] address
+/// The address to use when creating the "Source" object.
+///
+/// \return
+/// A "Source" JSON object that follows the formal JSON
+/// definition outlined by Microsoft.
+protocol::Source CreateAssemblySource(const lldb::SBTarget &target,
+ lldb::SBAddress &address);
+
/// Return true if the given line entry should be displayed as assembly.
///
/// \param[in] line_entry
>From f5fd76de3ad25b9cbf6ce065e06c98ff30b070a8 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 02:22:19 +0200
Subject: [PATCH 06/14] add breakpoint-assembly test
---
.../test/tools/lldb-dap/dap_server.py | 7 ++++
.../test/tools/lldb-dap/lldbdap_testcase.py | 10 +++++
.../lldb-dap/breakpoint-assembly/Makefile | 3 ++
.../TestDAP_breakpointAssembly.py | 42 +++++++++++++++++++
.../tools/lldb-dap/breakpoint-assembly/main.c | 14 +++++++
.../breakpoint/TestDAP_setBreakpoints.py | 1 +
.../TestDAP_setExceptionBreakpoints.py | 1 +
.../TestDAP_setFunctionBreakpoints.py | 1 +
8 files changed, 79 insertions(+)
create mode 100644 lldb/test/API/tools/lldb-dap/breakpoint-assembly/Makefile
create mode 100644 lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py
create mode 100644 lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
index 70fd0b0c419db..4a907a5e36901 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py
@@ -955,6 +955,13 @@ def request_setBreakpoints(self, file_path, line_array, data=None):
"""
(dir, base) = os.path.split(file_path)
source_dict = {"name": base, "path": file_path}
+ return self.request_setBreakpoints_with_source(source_dict, line_array, data)
+
+ def request_setBreakpointsAssembly(self, sourceReference, line_array, data=None):
+ source_dict = {"sourceReference": sourceReference}
+ return self.request_setBreakpoints_with_source(source_dict, line_array, data)
+
+ def request_setBreakpoints_with_source(self, source_dict, line_array, data=None):
args_dict = {
"source": source_dict,
"sourceModified": False,
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index afdc746ed0d0d..427f66a7da0c8 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -63,6 +63,16 @@ def set_source_breakpoints(self, source_path, lines, data=None):
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
return breakpoint_ids
+
+ def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
+ response = self.dap_server.request_setBreakpointsAssembly(source_reference, lines, data)
+ if response is None:
+ return []
+ breakpoints = response["body"]["breakpoints"]
+ breakpoint_ids = []
+ for breakpoint in breakpoints:
+ breakpoint_ids.append("%i" % (breakpoint["id"]))
+ return breakpoint_ids
def set_function_breakpoints(self, functions, condition=None, hitCondition=None):
"""Sets breakpoints by function name given an array of function names
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/Makefile b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/Makefile
new file mode 100644
index 0000000000000..10495940055b6
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py
new file mode 100644
index 0000000000000..ba9df3a18590b
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py
@@ -0,0 +1,42 @@
+"""
+Test lldb-dap setBreakpoints request
+"""
+
+
+import dap_server
+import shutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbdap_testcase
+import os
+
+
+class TestDAP_setBreakpointsAssembly(lldbdap_testcase.DAPTestCaseBase):
+ # @skipIfWindows
+ def test_functionality(self):
+ """Tests hitting assembly source breakpoints"""
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+
+ self.dap_server.request_evaluate(
+ "`settings set stop-disassembly-display no-debuginfo", context="repl"
+ )
+
+ assmebly_func_breakpoints = self.set_function_breakpoints(["assembly_func"])
+ self.continue_to_breakpoints(assmebly_func_breakpoints)
+
+ assembly_func_frame = self.get_stackFrames()[0]
+ self.assertIn(
+ "sourceReference",
+ assembly_func_frame.get("source"),
+ "Expected assembly source frame",
+ )
+
+ line = assembly_func_frame["line"]
+
+ # Set an assembly breakpoint in the next line and check that it's hit
+ assembly_breakpoint_ids = self.set_source_breakpoints_assembly(
+ assembly_func_frame["source"]["sourceReference"], [line + 1]
+ )
+ self.continue_to_breakpoints(assembly_breakpoint_ids)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c
new file mode 100644
index 0000000000000..350739006f903
--- /dev/null
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c
@@ -0,0 +1,14 @@
+#include <stddef.h>
+
+__attribute__((nodebug)) int assembly_func(int n) {
+ n += 1;
+ n += 2;
+ n += 3;
+
+ return n;
+}
+
+int main(int argc, char const *argv[]) {
+ assembly_func(10);
+ return 0;
+}
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
index 26df2573555df..aae1251b17c93 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setBreakpoints.py
@@ -12,6 +12,7 @@
import os
+ at skip("Temporarily disable the breakpoint tests")
class TestDAP_setBreakpoints(lldbdap_testcase.DAPTestCaseBase):
def setUp(self):
lldbdap_testcase.DAPTestCaseBase.setUp(self)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
index 92ac66cd44c5d..4dc8c5b3c7ded 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setExceptionBreakpoints.py
@@ -10,6 +10,7 @@
import lldbdap_testcase
+ at skip("Temporarily disable the breakpoint tests")
class TestDAP_setExceptionBreakpoints(lldbdap_testcase.DAPTestCaseBase):
@skipIfWindows
def test_functionality(self):
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
index 946595f639edc..baaca4d974d5d 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint/TestDAP_setFunctionBreakpoints.py
@@ -10,6 +10,7 @@
import lldbdap_testcase
+ at skip("Temporarily disable the breakpoint tests")
class TestDAP_setFunctionBreakpoints(lldbdap_testcase.DAPTestCaseBase):
@skipIfWindows
def test_set_and_clear(self):
>From 40f68e418bfbb6564b3834382c4a33a3104fc33d Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 10:23:11 +0200
Subject: [PATCH 07/14] python format
---
.../lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
index 427f66a7da0c8..3bf649a087fdb 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py
@@ -63,9 +63,11 @@ def set_source_breakpoints(self, source_path, lines, data=None):
for breakpoint in breakpoints:
breakpoint_ids.append("%i" % (breakpoint["id"]))
return breakpoint_ids
-
+
def set_source_breakpoints_assembly(self, source_reference, lines, data=None):
- response = self.dap_server.request_setBreakpointsAssembly(source_reference, lines, data)
+ response = self.dap_server.request_setBreakpointsAssembly(
+ source_reference, lines, data
+ )
if response is None:
return []
breakpoints = response["body"]["breakpoints"]
>From 199512fd7a0900d45070b95dd52ef5ef136e2719 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 10:54:43 +0200
Subject: [PATCH 08/14] restore SBFileSpec and fix assembly breakpoints CR
---
lldb/include/lldb/API/SBFileSpec.h | 2 -
lldb/source/API/SBFileSpec.cpp | 7 ---
lldb/tools/lldb-dap/DAP.h | 2 +-
.../Handler/BreakpointLocationsHandler.cpp | 47 ++++++++++---------
lldb/tools/lldb-dap/Handler/RequestHandler.h | 17 ++++---
.../Handler/SetBreakpointsRequestHandler.cpp | 9 ++--
lldb/tools/lldb-dap/JSONUtils.cpp | 6 +--
lldb/tools/lldb-dap/LLDBUtils.cpp | 10 ++++
lldb/tools/lldb-dap/LLDBUtils.h | 10 ++++
9 files changed, 60 insertions(+), 50 deletions(-)
diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h
index 303cb7d712cbf..1bb28b2ddab01 100644
--- a/lldb/include/lldb/API/SBFileSpec.h
+++ b/lldb/include/lldb/API/SBFileSpec.h
@@ -54,8 +54,6 @@ class LLDB_API SBFileSpec {
uint32_t GetPath(char *dst_path, size_t dst_len) const;
- bool GetPath(lldb::SBStream &dst_path) const;
-
static int ResolvePath(const char *src_path, char *dst_path, size_t dst_len);
bool GetDescription(lldb::SBStream &description) const;
diff --git a/lldb/source/API/SBFileSpec.cpp b/lldb/source/API/SBFileSpec.cpp
index cb44dac1d4fcc..f18857f59171a 100644
--- a/lldb/source/API/SBFileSpec.cpp
+++ b/lldb/source/API/SBFileSpec.cpp
@@ -148,13 +148,6 @@ uint32_t SBFileSpec::GetPath(char *dst_path, size_t dst_len) const {
return result;
}
-bool SBFileSpec::GetPath(SBStream &dst_path) const {
- LLDB_INSTRUMENT_VA(this, dst_path);
-
- std::string path = m_opaque_up->GetPath();
- return dst_path->PutCString(path.c_str()) > 0;
-}
-
const lldb_private::FileSpec *SBFileSpec::operator->() const {
return m_opaque_up.get();
}
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index b0fe265b7bca1..20f95be792f41 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -222,7 +222,7 @@ struct DAP {
/// @}
/// Number of lines of assembly code to show when no debug info is available.
- uint32_t number_of_assembly_lines_for_nodebug = 32;
+ static constexpr uint32_t number_of_assembly_lines_for_nodebug = 32;
/// Creates a new DAP sessions.
///
diff --git a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
index c4d658caeee2d..794b83a9e0e1e 100644
--- a/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/BreakpointLocationsHandler.cpp
@@ -8,6 +8,7 @@
#include "DAP.h"
#include "RequestHandler.h"
+#include <optional>
#include <vector>
namespace lldb_dap {
@@ -24,15 +25,15 @@ BreakpointLocationsRequestHandler::Run(
uint32_t end_column =
args.endColumn.value_or(std::numeric_limits<uint32_t>::max());
- // Find all relevant lines & columns
- llvm::SmallVector<std::pair<uint32_t, uint32_t>, 8> locations;
- if (args.source.sourceReference) {
- AddAssemblyBreakpointLocations(locations, *args.source.sourceReference,
- start_line, end_line);
- } else {
+ // Find all relevant lines & columns.
+ std::vector<std::pair<uint32_t, uint32_t>> locations;
+ if (args.source.sourceReference)
+ locations = GetAssemblyBreakpointLocations(*args.source.sourceReference,
+ start_line, end_line);
+ else {
std::string path = args.source.path.value_or("");
- AddSourceBreakpointLocations(locations, std::move(path), start_line,
- start_column, end_line, end_column);
+ locations = GetSourceBreakpointLocations(
+ std::move(path), start_line, start_column, end_line, end_column);
}
// The line entries are sorted by addresses, but we must return the list
@@ -41,23 +42,19 @@ BreakpointLocationsRequestHandler::Run(
locations.erase(llvm::unique(locations), locations.end());
std::vector<protocol::BreakpointLocation> breakpoint_locations;
- for (auto &l : locations) {
- protocol::BreakpointLocation lc;
- lc.line = l.first;
- lc.column = l.second;
- breakpoint_locations.push_back(std::move(lc));
- }
+ for (auto &l : locations)
+ breakpoint_locations.push_back(
+ {l.first, l.second, std::nullopt, std::nullopt});
return protocol::BreakpointLocationsResponseBody{
/*breakpoints=*/std::move(breakpoint_locations)};
}
-template <unsigned N>
-void BreakpointLocationsRequestHandler::AddSourceBreakpointLocations(
- llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
+std::vector<std::pair<uint32_t, uint32_t>>
+BreakpointLocationsRequestHandler::GetSourceBreakpointLocations(
std::string path, uint32_t start_line, uint32_t start_column,
uint32_t end_line, uint32_t end_column) const {
-
+ std::vector<std::pair<uint32_t, uint32_t>> locations;
lldb::SBFileSpec file_spec(path.c_str(), true);
lldb::SBSymbolContextList compile_units =
dap.target.FindCompileUnits(file_spec);
@@ -101,19 +98,21 @@ void BreakpointLocationsRequestHandler::AddSourceBreakpointLocations(
locations.emplace_back(line, column);
}
}
+
+ return locations;
}
-template <unsigned N>
-void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
- llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
+std::vector<std::pair<uint32_t, uint32_t>>
+BreakpointLocationsRequestHandler::GetAssemblyBreakpointLocations(
int64_t sourceReference, uint32_t start_line, uint32_t end_line) const {
+ std::vector<std::pair<uint32_t, uint32_t>> locations;
lldb::SBAddress address(sourceReference, dap.target);
if (!address.IsValid())
- return;
+ return locations;
lldb::SBSymbol symbol = address.GetSymbol();
if (!symbol.IsValid())
- return;
+ return locations;
// start_line is relative to the symbol's start address
lldb::SBInstructionList insts = symbol.GetInstructions(dap.target);
@@ -121,6 +120,8 @@ void BreakpointLocationsRequestHandler::AddAssemblyBreakpointLocations(
++i) {
locations.emplace_back(i, 1);
}
+
+ return locations;
}
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 80898d1ee5ef1..e708abb50d5c0 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -23,6 +23,7 @@
#include <optional>
#include <type_traits>
#include <variant>
+#include <vector>
template <typename T> struct is_optional : std::false_type {};
@@ -234,15 +235,13 @@ class BreakpointLocationsRequestHandler
llvm::Expected<protocol::BreakpointLocationsResponseBody>
Run(const protocol::BreakpointLocationsArguments &args) const override;
- template <unsigned N>
- void AddSourceBreakpointLocations(
- llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
- std::string path, uint32_t start_line, uint32_t start_column,
- uint32_t end_line, uint32_t end_column) const;
- template <unsigned N>
- void AddAssemblyBreakpointLocations(
- llvm::SmallVector<std::pair<uint32_t, uint32_t>, N> &locations,
- int64_t sourceReference, uint32_t start_line, uint32_t end_line) const;
+ std::vector<std::pair<uint32_t, uint32_t>>
+ GetSourceBreakpointLocations(std::string path, uint32_t start_line,
+ uint32_t start_column, uint32_t end_line,
+ uint32_t end_column) const;
+ std::vector<std::pair<uint32_t, uint32_t>>
+ GetAssemblyBreakpointLocations(int64_t sourceReference, uint32_t start_line,
+ uint32_t end_line) const;
};
class CompletionsRequestHandler : public LegacyRequestHandler {
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
index 7b401f06e9a85..bf0b584753c07 100644
--- a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -103,9 +103,10 @@ SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
return response_breakpoints;
lldb::SBSymbol symbol = address.GetSymbol();
- if (!symbol.IsValid())
- return response_breakpoints; // Not yet supporting breakpoints in assembly
- // without a valid symbol
+ if (!symbol.IsValid()) {
+ // Not yet supporting breakpoints in assembly without a valid symbol.
+ return response_breakpoints;
+ }
llvm::DenseMap<uint32_t, SourceBreakpoint> request_bps;
if (breakpoints) {
@@ -115,7 +116,7 @@ SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
const auto [iv, inserted] =
dap.assembly_breakpoints[sourceReference].try_emplace(
src_bp.GetLine(), src_bp);
- // We check if this breakpoint already exists to update it
+ // We check if this breakpoint already exists to update it.
if (inserted)
iv->getSecond().SetBreakpoint(symbol);
else
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index c8151c3d64ea4..1d2a6ff60e502 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -542,11 +542,9 @@ protocol::Source CreateAssemblySource(const lldb::SBTarget &target,
if (module.IsValid()) {
lldb::SBFileSpec file_spec = module.GetFileSpec();
if (file_spec.IsValid()) {
- lldb::SBStream module_path;
- if (file_spec.GetPath(module_path)) {
- std::string path = module_path.GetData();
+ std::string path = GetSBFileSpecPath(file_spec);
+ if (!path.empty())
source.path = path + '`' + name;
- }
}
}
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 0e7bb2b9058a7..3c7623ec1215d 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -20,6 +20,7 @@
#include "llvm/Support/JSON.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstring>
#include <mutex>
#include <system_error>
@@ -242,4 +243,13 @@ ScopeSyncMode::ScopeSyncMode(lldb::SBDebugger &debugger)
ScopeSyncMode::~ScopeSyncMode() { m_debugger.SetAsync(m_async); }
+std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec) {
+ const auto directory_length = ::strlen(file_spec.GetDirectory());
+ const auto file_name_length = ::strlen(file_spec.GetFilename());
+
+ std::string path(directory_length + file_name_length + 2, '\0');
+ file_spec.GetPath(path.data(), path.length());
+ return path;
+}
+
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/LLDBUtils.h b/lldb/tools/lldb-dap/LLDBUtils.h
index 711fc6051231c..7fdf4b859ee61 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.h
+++ b/lldb/tools/lldb-dap/LLDBUtils.h
@@ -13,6 +13,7 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEnvironment.h"
#include "lldb/API/SBError.h"
+#include "lldb/API/SBFileSpec.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -161,6 +162,15 @@ uint32_t GetLLDBFrameID(uint64_t dap_frame_id);
lldb::SBEnvironment
GetEnvironmentFromArguments(const llvm::json::Object &arguments);
+/// Gets an SBFileSpec and returns its path as a string.
+///
+/// \param[in] file_spec
+/// The file spec.
+///
+/// \return
+/// The file path as a string.
+std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec);
+
/// Helper for sending telemetry to lldb server, if client-telemetry is enabled.
class TelemetryDispatcher {
public:
>From dbad33b314bb59f6e0d22fd07dddb35e2a0e30d9 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 12:57:59 +0200
Subject: [PATCH 09/14] abstracted source breakpoints maps by DAP
---
lldb/tools/lldb-dap/Breakpoint.cpp | 4 +-
lldb/tools/lldb-dap/DAP.cpp | 75 +++++++++++
lldb/tools/lldb-dap/DAP.h | 29 +++-
lldb/tools/lldb-dap/Handler/RequestHandler.h | 9 --
.../Handler/SetBreakpointsRequestHandler.cpp | 125 +-----------------
lldb/tools/lldb-dap/SourceBreakpoint.cpp | 54 +++++---
lldb/tools/lldb-dap/SourceBreakpoint.h | 7 +-
7 files changed, 140 insertions(+), 163 deletions(-)
diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp
index a54a34e0f936d..fd7531f42c518 100644
--- a/lldb/tools/lldb-dap/Breakpoint.cpp
+++ b/lldb/tools/lldb-dap/Breakpoint.cpp
@@ -71,10 +71,10 @@ protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() {
auto line_entry = bp_addr.GetLineEntry();
if (!ShouldDisplayAssemblySource(line_entry, stop_disassembly_display)) {
const auto line = line_entry.GetLine();
- if (line != UINT32_MAX)
+ if (line != LLDB_INVALID_LINE_NUMBER)
breakpoint.line = line;
const auto column = line_entry.GetColumn();
- if (column != 0)
+ if (column != LLDB_INVALID_COLUMN_NUMBER)
breakpoint.column = column;
breakpoint.source = CreateSource(line_entry);
} else {
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 0d5eba6c40961..1fe46fc619d73 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1620,6 +1620,81 @@ void DAP::EventThread() {
}
}
+std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints(
+ const protocol::Source &source,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints) {
+ std::vector<protocol::Breakpoint> response_breakpoints;
+ if (source.sourceReference) {
+ // breakpoint set by assembly source.
+ auto &existing_breakpoints_pos =
+ m_source_assembly_breakpoints[*source.sourceReference];
+ response_breakpoints =
+ SetSourceBreakpoints(source, breakpoints, existing_breakpoints_pos);
+ } else {
+ // breakpoint set by a regular source file.
+ const auto path = source.path.value_or("");
+ auto &existing_breakpoints_pos = m_source_breakpoints[path];
+ response_breakpoints =
+ SetSourceBreakpoints(source, breakpoints, existing_breakpoints_pos);
+ }
+
+ return response_breakpoints;
+}
+
+std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints(
+ const protocol::Source &source,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints,
+ SourceBreakpointMap &existing_breakpoints) {
+ std::vector<protocol::Breakpoint> response_breakpoints;
+
+ SourceBreakpointMap request_breakpoints;
+ if (breakpoints) {
+ for (const auto &bp : *breakpoints) {
+ SourceBreakpoint src_bp(*this, bp, source);
+ std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(),
+ src_bp.GetColumn());
+ request_breakpoints.try_emplace(bp_pos, src_bp);
+
+ const auto [iv, inserted] =
+ existing_breakpoints.try_emplace(bp_pos, src_bp);
+ // We check if this breakpoint already exists to update it.
+ if (inserted)
+ iv->second.SetBreakpoint();
+ else
+ iv->second.UpdateBreakpoint(src_bp);
+
+ protocol::Breakpoint response_breakpoint =
+ iv->second.ToProtocolBreakpoint();
+ response_breakpoint.source = source;
+
+ if (!response_breakpoint.line &&
+ src_bp.GetLine() != LLDB_INVALID_LINE_NUMBER)
+ response_breakpoint.line = src_bp.GetLine();
+ if (!response_breakpoint.column &&
+ src_bp.GetColumn() != LLDB_INVALID_COLUMN_NUMBER)
+ response_breakpoint.column = src_bp.GetColumn();
+ response_breakpoints.push_back(response_breakpoint);
+ }
+ }
+
+ // Delete any breakpoints in this source file that aren't in the
+ // request_bps set. There is no call to remove breakpoints other than
+ // calling this function with a smaller or empty "breakpoints" list.
+ for (auto it = existing_breakpoints.begin();
+ it != existing_breakpoints.end();) {
+ auto request_pos = request_breakpoints.find(it->first);
+ if (request_pos == request_breakpoints.end()) {
+ // This breakpoint no longer exists in this source file, delete it
+ target.BreakpointDelete(it->second.GetID());
+ it = existing_breakpoints.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ return response_breakpoints;
+}
+
void DAP::RegisterRequests() {
RegisterRequest<AttachRequestHandler>();
RegisterRequest<BreakpointLocationsRequestHandler>();
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 20f95be792f41..3a0a7fc1678ba 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -60,7 +60,7 @@
namespace lldb_dap {
-typedef llvm::DenseMap<std::pair<uint32_t, uint32_t>, SourceBreakpoint>
+typedef std::map<std::pair<uint32_t, uint32_t>, SourceBreakpoint>
SourceBreakpointMap;
typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
typedef llvm::DenseMap<lldb::addr_t, InstructionBreakpoint>
@@ -168,9 +168,6 @@ struct DAP {
lldb::SBTarget target;
Variables variables;
lldb::SBBroadcaster broadcaster;
- llvm::StringMap<SourceBreakpointMap> source_breakpoints;
- llvm::DenseMap<int64_t, llvm::DenseMap<uint32_t, SourceBreakpoint>>
- assembly_breakpoints;
FunctionBreakpointMap function_breakpoints;
InstructionBreakpointMap instruction_breakpoints;
std::optional<std::vector<ExceptionBreakpoint>> exception_breakpoints;
@@ -428,7 +425,28 @@ struct DAP {
void StartEventThread();
void StartProgressEventThread();
+ /// Sets the given protocol `breakpoints` in the given `source`, while
+ /// removing any existing breakpoints in the given source if they are not in
+ /// `breakpoint`.
+ ///
+ /// \param[in] source
+ /// The relevant source of the breakpoints.
+ ///
+ /// \param[in] breakpoints
+ /// The breakpoints to set.
+ ///
+ /// \return a vector of the breakpoints that were set.
+ std::vector<protocol::Breakpoint> SetSourceBreakpoints(
+ const protocol::Source &source,
+ const std::optional<std::vector<protocol::SourceBreakpoint>>
+ &breakpoints);
+
private:
+ std::vector<protocol::Breakpoint> SetSourceBreakpoints(
+ const protocol::Source &source,
+ const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints,
+ SourceBreakpointMap &existing_breakpoints);
+
/// Registration of request handler.
/// @{
void RegisterRequests();
@@ -457,6 +475,9 @@ struct DAP {
std::mutex m_active_request_mutex;
const protocol::Request *m_active_request;
+
+ llvm::StringMap<SourceBreakpointMap> m_source_breakpoints;
+ llvm::DenseMap<int64_t, SourceBreakpointMap> m_source_assembly_breakpoints;
};
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index e708abb50d5c0..54f728414021e 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -388,15 +388,6 @@ class SetBreakpointsRequestHandler
}
llvm::Expected<protocol::SetBreakpointsResponseBody>
Run(const protocol::SetBreakpointsArguments &args) const override;
-
- std::vector<protocol::Breakpoint> SetSourceBreakpoints(
- const protocol::Source &source,
- const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
- const;
- std::vector<protocol::Breakpoint> SetAssemblyBreakpoints(
- const protocol::Source &source,
- const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
- const;
};
class SetExceptionBreakpointsRequestHandler : public LegacyRequestHandler {
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
index bf0b584753c07..0ff88f62f8f51 100644
--- a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -22,130 +22,9 @@ namespace lldb_dap {
llvm::Expected<protocol::SetBreakpointsResponseBody>
SetBreakpointsRequestHandler::Run(
const protocol::SetBreakpointsArguments &args) const {
- const auto &source = args.source;
- std::vector<protocol::Breakpoint> response_breakpoints;
- if (source.sourceReference)
- response_breakpoints = SetAssemblyBreakpoints(source, args.breakpoints);
- else if (source.path)
- response_breakpoints = SetSourceBreakpoints(source, args.breakpoints);
-
+ const auto response_breakpoints =
+ dap.SetSourceBreakpoints(args.source, args.breakpoints);
return protocol::SetBreakpointsResponseBody{std::move(response_breakpoints)};
}
-std::vector<protocol::Breakpoint>
-SetBreakpointsRequestHandler::SetSourceBreakpoints(
- const protocol::Source &source,
- const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
- const {
- std::vector<protocol::Breakpoint> response_breakpoints;
- std::string path = source.path.value_or("");
-
- // Decode the source breakpoint infos for this "setBreakpoints" request
- SourceBreakpointMap request_bps;
- // "breakpoints" may be unset, in which case we treat it the same as being set
- // to an empty array.
- if (breakpoints) {
- for (const auto &bp : *breakpoints) {
- SourceBreakpoint src_bp(dap, bp);
- std::pair<uint32_t, uint32_t> bp_pos(src_bp.GetLine(),
- src_bp.GetColumn());
- request_bps.try_emplace(bp_pos, src_bp);
- const auto [iv, inserted] =
- dap.source_breakpoints[path].try_emplace(bp_pos, src_bp);
- // We check if this breakpoint already exists to update it
- if (inserted)
- iv->getSecond().SetBreakpoint(path.data());
- else
- iv->getSecond().UpdateBreakpoint(src_bp);
-
- protocol::Breakpoint response_bp = iv->getSecond().ToProtocolBreakpoint();
-
- // Use the path from the request if it is set
- if (!path.empty())
- response_bp.source = CreateSource(path);
-
- if (!response_bp.line)
- response_bp.line = src_bp.GetLine();
- if (!response_bp.column)
- response_bp.column = src_bp.GetColumn();
- response_breakpoints.push_back(response_bp);
- }
- }
-
- // Delete any breakpoints in this source file that aren't in the
- // request_bps set. There is no call to remove breakpoints other than
- // calling this function with a smaller or empty "breakpoints" list.
- auto old_src_bp_pos = dap.source_breakpoints.find(path);
- if (old_src_bp_pos != dap.source_breakpoints.end()) {
- for (auto &old_bp : old_src_bp_pos->second) {
- auto request_pos = request_bps.find(old_bp.first);
- if (request_pos == request_bps.end()) {
- // This breakpoint no longer exists in this source file, delete it
- dap.target.BreakpointDelete(old_bp.second.GetID());
- old_src_bp_pos->second.erase(old_bp.first);
- }
- }
- }
-
- return response_breakpoints;
-}
-
-std::vector<protocol::Breakpoint>
-SetBreakpointsRequestHandler::SetAssemblyBreakpoints(
- const protocol::Source &source,
- const std::optional<std::vector<protocol::SourceBreakpoint>> &breakpoints)
- const {
- std::vector<protocol::Breakpoint> response_breakpoints;
- int64_t sourceReference = source.sourceReference.value_or(0);
-
- lldb::SBAddress address(sourceReference, dap.target);
- if (!address.IsValid())
- return response_breakpoints;
-
- lldb::SBSymbol symbol = address.GetSymbol();
- if (!symbol.IsValid()) {
- // Not yet supporting breakpoints in assembly without a valid symbol.
- return response_breakpoints;
- }
-
- llvm::DenseMap<uint32_t, SourceBreakpoint> request_bps;
- if (breakpoints) {
- for (const auto &bp : *breakpoints) {
- SourceBreakpoint src_bp(dap, bp);
- request_bps.try_emplace(src_bp.GetLine(), src_bp);
- const auto [iv, inserted] =
- dap.assembly_breakpoints[sourceReference].try_emplace(
- src_bp.GetLine(), src_bp);
- // We check if this breakpoint already exists to update it.
- if (inserted)
- iv->getSecond().SetBreakpoint(symbol);
- else
- iv->getSecond().UpdateBreakpoint(src_bp);
-
- protocol::Breakpoint response_bp = iv->getSecond().ToProtocolBreakpoint();
- response_bp.source = source;
- if (!response_bp.line)
- response_bp.line = src_bp.GetLine();
- if (bp.column)
- response_bp.column = *bp.column;
- response_breakpoints.push_back(response_bp);
- }
- }
-
- // Delete existing breakpoints for this sourceReference that are not in the
- // request_bps set.
- auto old_src_bp_pos = dap.assembly_breakpoints.find(sourceReference);
- if (old_src_bp_pos != dap.assembly_breakpoints.end()) {
- for (auto &old_bp : old_src_bp_pos->second) {
- auto request_pos = request_bps.find(old_bp.first);
- if (request_pos == request_bps.end()) {
- dap.target.BreakpointDelete(old_bp.second.GetID());
- old_src_bp_pos->second.erase(old_bp.first);
- }
- }
- }
-
- return response_breakpoints;
-}
-
} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index 938b8fb8bcdda..50ebfbe8aef20 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -29,39 +29,49 @@
namespace lldb_dap {
SourceBreakpoint::SourceBreakpoint(DAP &dap,
- const protocol::SourceBreakpoint &breakpoint)
+ const protocol::SourceBreakpoint &breakpoint,
+ const protocol::Source &source)
: Breakpoint(dap, breakpoint.condition, breakpoint.hitCondition),
- m_log_message(breakpoint.logMessage.value_or("")),
+ m_log_message(breakpoint.logMessage.value_or("")), m_source(source),
m_line(breakpoint.line),
m_column(breakpoint.column.value_or(LLDB_INVALID_COLUMN_NUMBER)) {}
-void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
- lldb::SBMutex lock = m_dap.GetAPIMutex();
- std::lock_guard<lldb::SBMutex> guard(lock);
-
- lldb::SBFileSpecList module_list;
- m_bp = m_dap.target.BreakpointCreateByLocation(
- source_path.str().c_str(), m_line, m_column, 0, module_list);
- if (!m_log_message.empty())
- SetLogMessage();
- Breakpoint::SetBreakpoint();
-}
-
-void SourceBreakpoint::SetBreakpoint(lldb::SBSymbol &symbol) {
+void SourceBreakpoint::SetBreakpoint() {
lldb::SBMutex lock = m_dap.GetAPIMutex();
std::lock_guard<lldb::SBMutex> guard(lock);
if (m_line == 0)
return;
- lldb::SBInstructionList inst_list =
- m_dap.target.ReadInstructions(symbol.GetStartAddress(), m_line);
- if (inst_list.GetSize() < m_line)
- return;
- lldb::SBAddress address =
- inst_list.GetInstructionAtIndex(m_line - 1).GetAddress();
+ if (m_source.sourceReference) {
+ // breakpoint set by assembly source.
+ lldb::SBAddress source_address(*m_source.sourceReference, m_dap.target);
+ if (!source_address.IsValid())
+ return;
+
+ lldb::SBSymbol symbol = source_address.GetSymbol();
+ if (!symbol.IsValid()) {
+ // Not yet supporting breakpoints in assembly without a valid symbol.
+ return;
+ }
+
+ lldb::SBInstructionList inst_list =
+ m_dap.target.ReadInstructions(symbol.GetStartAddress(), m_line);
+ if (inst_list.GetSize() < m_line)
+ return;
+
+ lldb::SBAddress address =
+ inst_list.GetInstructionAtIndex(m_line - 1).GetAddress();
+
+ m_bp = m_dap.target.BreakpointCreateBySBAddress(address);
+ } else {
+ // breakpoint set by a regular source file.
+ const auto source_path = m_source.path.value_or("");
+ lldb::SBFileSpecList module_list;
+ m_bp = m_dap.target.BreakpointCreateByLocation(source_path.c_str(), m_line,
+ m_column, 0, module_list);
+ }
- m_bp = m_dap.target.BreakpointCreateBySBAddress(address);
if (!m_log_message.empty())
SetLogMessage();
Breakpoint::SetBreakpoint();
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h
index 8589800e50983..3221ecbf28ece 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.h
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.h
@@ -22,11 +22,11 @@ namespace lldb_dap {
class SourceBreakpoint : public Breakpoint {
public:
- SourceBreakpoint(DAP &d, const protocol::SourceBreakpoint &breakpoint);
+ SourceBreakpoint(DAP &d, const protocol::SourceBreakpoint &breakpoint,
+ const protocol::Source &source);
// Set this breakpoint in LLDB as a new breakpoint
- void SetBreakpoint(const llvm::StringRef source_path);
- void SetBreakpoint(lldb::SBSymbol &symbol);
+ void SetBreakpoint();
void UpdateBreakpoint(const SourceBreakpoint &request_bp);
void SetLogMessage();
@@ -63,6 +63,7 @@ class SourceBreakpoint : public Breakpoint {
std::string m_log_message;
std::vector<LogMessagePart> m_log_message_parts;
+ protocol::Source m_source; /// The original breakpoint source.
uint32_t m_line; ///< The source line of the breakpoint or logpoint
uint32_t m_column; ///< An optional source column of the breakpoint
};
>From 2e9edca37c0953e2d2a6cf2d278bb353f1e0960b Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 13:39:05 +0200
Subject: [PATCH 10/14] improve assembvly breakpoint test to check clear
---
.../TestDAP_breakpointAssembly.py | 17 +++++++++++++++--
.../tools/lldb-dap/breakpoint-assembly/main.c | 4 +++-
2 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py
index ba9df3a18590b..dacc1cd8349f1 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/TestDAP_breakpointAssembly.py
@@ -6,7 +6,7 @@
import dap_server
import shutil
from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
+from lldbsuite.test.lldbtest import line_number
from lldbsuite.test import lldbutil
import lldbdap_testcase
import os
@@ -23,6 +23,9 @@ def test_functionality(self):
"`settings set stop-disassembly-display no-debuginfo", context="repl"
)
+ finish_line = line_number("main.c", "// Break here")
+ finish_breakpoints = self.set_source_breakpoints("main.c", [finish_line])
+
assmebly_func_breakpoints = self.set_function_breakpoints(["assembly_func"])
self.continue_to_breakpoints(assmebly_func_breakpoints)
@@ -36,7 +39,17 @@ def test_functionality(self):
line = assembly_func_frame["line"]
# Set an assembly breakpoint in the next line and check that it's hit
+ source_reference = assembly_func_frame["source"]["sourceReference"]
assembly_breakpoint_ids = self.set_source_breakpoints_assembly(
- assembly_func_frame["source"]["sourceReference"], [line + 1]
+ source_reference, [line + 1]
)
self.continue_to_breakpoints(assembly_breakpoint_ids)
+
+ # Continue again and verify it hits in the next function call
+ self.continue_to_breakpoints(assmebly_func_breakpoints)
+ self.continue_to_breakpoints(assembly_breakpoint_ids)
+
+ # Clear the breakpoint and then check that the assembly breakpoint does not hit next time
+ self.set_source_breakpoints_assembly(source_reference, [])
+ self.continue_to_breakpoints(assmebly_func_breakpoints)
+ self.continue_to_breakpoints(finish_breakpoints)
diff --git a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c
index 350739006f903..e3a21df11958f 100644
--- a/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c
+++ b/lldb/test/API/tools/lldb-dap/breakpoint-assembly/main.c
@@ -10,5 +10,7 @@ __attribute__((nodebug)) int assembly_func(int n) {
int main(int argc, char const *argv[]) {
assembly_func(10);
- return 0;
+ assembly_func(20);
+ assembly_func(30);
+ return 0; // Break here
}
>From 0515c6dc6e46b6296621e871b43286ae88ea9b6b Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 13:52:40 +0200
Subject: [PATCH 11/14] fix GetSBFileSpecPath extra char
---
lldb/tools/lldb-dap/LLDBUtils.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lldb/tools/lldb-dap/LLDBUtils.cpp b/lldb/tools/lldb-dap/LLDBUtils.cpp
index 3c7623ec1215d..fe0bcda19b4cd 100644
--- a/lldb/tools/lldb-dap/LLDBUtils.cpp
+++ b/lldb/tools/lldb-dap/LLDBUtils.cpp
@@ -247,8 +247,8 @@ std::string GetSBFileSpecPath(const lldb::SBFileSpec &file_spec) {
const auto directory_length = ::strlen(file_spec.GetDirectory());
const auto file_name_length = ::strlen(file_spec.GetFilename());
- std::string path(directory_length + file_name_length + 2, '\0');
- file_spec.GetPath(path.data(), path.length());
+ std::string path(directory_length + file_name_length + 1, '\0');
+ file_spec.GetPath(path.data(), path.length() + 1);
return path;
}
>From 9dbca55d01c7faddc9df4586ba25c6fac421d909 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 13:59:53 +0200
Subject: [PATCH 12/14] restore SBFileSpec changes
---
lldb/include/lldb/API/SBFileSpec.h | 1 -
lldb/source/API/SBFileSpec.cpp | 1 -
lldb/tools/lldb-dap/DAP.cpp | 8 ++++----
3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h
index 1bb28b2ddab01..36641843aabeb 100644
--- a/lldb/include/lldb/API/SBFileSpec.h
+++ b/lldb/include/lldb/API/SBFileSpec.h
@@ -10,7 +10,6 @@
#define LLDB_API_SBFILESPEC_H
#include "lldb/API/SBDefines.h"
-#include "lldb/API/SBStream.h"
namespace lldb {
diff --git a/lldb/source/API/SBFileSpec.cpp b/lldb/source/API/SBFileSpec.cpp
index f18857f59171a..a7df9afc4b8eb 100644
--- a/lldb/source/API/SBFileSpec.cpp
+++ b/lldb/source/API/SBFileSpec.cpp
@@ -19,7 +19,6 @@
#include <cinttypes>
#include <climits>
-#include <string>
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 1fe46fc619d73..d7ef886dd2419 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1626,16 +1626,16 @@ std::vector<protocol::Breakpoint> DAP::SetSourceBreakpoints(
std::vector<protocol::Breakpoint> response_breakpoints;
if (source.sourceReference) {
// breakpoint set by assembly source.
- auto &existing_breakpoints_pos =
+ auto &existing_breakpoints =
m_source_assembly_breakpoints[*source.sourceReference];
response_breakpoints =
- SetSourceBreakpoints(source, breakpoints, existing_breakpoints_pos);
+ SetSourceBreakpoints(source, breakpoints, existing_breakpoints);
} else {
// breakpoint set by a regular source file.
const auto path = source.path.value_or("");
- auto &existing_breakpoints_pos = m_source_breakpoints[path];
+ auto &existing_breakpoints = m_source_breakpoints[path];
response_breakpoints =
- SetSourceBreakpoints(source, breakpoints, existing_breakpoints_pos);
+ SetSourceBreakpoints(source, breakpoints, existing_breakpoints);
}
return response_breakpoints;
>From 396970d6a46063450741b6b0c9c528078e433e24 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 14:01:28 +0200
Subject: [PATCH 13/14] single line if with comments curly braces
---
lldb/tools/lldb-dap/JSONUtils.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp
index 1d2a6ff60e502..dcc25c9212432 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -661,10 +661,11 @@ CreateStackFrame(lldb::SBFrame &frame, lldb::SBFormat &format,
frame_name = name;
}
- if (frame_name.empty())
+ if (frame_name.empty()) {
// If the function name is unavailable, display the pc address as a 16-digit
// hex string, e.g. "0x0000000000012345"
frame_name = GetLoadAddressString(frame.GetPC());
+ }
// We only include `[opt]` if a custom frame format is not specified.
if (!format && frame.GetFunction().GetIsOptimized())
>From 7a0e0eeb1232028e535d2057198c8e8a7f0487d6 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sun, 18 May 2025 14:06:40 +0200
Subject: [PATCH 14/14] unecessary include
---
lldb/tools/lldb-dap/Handler/RequestHandler.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 54f728414021e..4670e23ca33d4 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -16,7 +16,6 @@
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
More information about the lldb-commits
mailing list