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 <elyron...@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 -@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 -@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 -@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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 +@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 +@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 +@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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 <elyron...@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" _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits