https://github.com/ZequanWu created https://github.com/llvm/llvm-project/pull/80753
This adds a layer between `SounceBreakpoint`/`FunctionBreakpoint` and `BreakpointBase` to have better separation and encapsulation so we are not directly operating on `SBBreakpoint`. I basically moved the `SBBreakpoint` and the methods that requires it from `BreakpointBase` to `Breakpoint`. This allows adding support for data watchpoint easier by sharing the logic inside `BreakpointBase`. >From c4b767909a9ffc2a3015dc9021e4c265da0d877d Mon Sep 17 00:00:00 2001 From: Zequan Wu <zequa...@google.com> Date: Mon, 5 Feb 2024 17:26:48 -0500 Subject: [PATCH] [lldb-dap][NFC] Add Breakpoint struct to share common logic. --- lldb/tools/lldb-dap/Breakpoint.cpp | 182 ++++++++++++++++++ lldb/tools/lldb-dap/Breakpoint.h | 34 ++++ lldb/tools/lldb-dap/BreakpointBase.cpp | 113 ----------- lldb/tools/lldb-dap/BreakpointBase.h | 12 +- lldb/tools/lldb-dap/CMakeLists.txt | 1 + lldb/tools/lldb-dap/FunctionBreakpoint.cpp | 12 +- lldb/tools/lldb-dap/FunctionBreakpoint.h | 4 +- lldb/tools/lldb-dap/JSONUtils.cpp | 46 +---- lldb/tools/lldb-dap/JSONUtils.h | 5 +- lldb/tools/lldb-dap/SourceBreakpoint.cpp | 12 +- lldb/tools/lldb-dap/SourceBreakpoint.h | 6 +- lldb/tools/lldb-dap/lldb-dap.cpp | 17 +- .../gn/secondary/lldb/tools/lldb-dap/BUILD.gn | 1 + 13 files changed, 248 insertions(+), 197 deletions(-) create mode 100644 lldb/tools/lldb-dap/Breakpoint.cpp create mode 100644 lldb/tools/lldb-dap/Breakpoint.h diff --git a/lldb/tools/lldb-dap/Breakpoint.cpp b/lldb/tools/lldb-dap/Breakpoint.cpp new file mode 100644 index 00000000000000..4ccf353b06cccc --- /dev/null +++ b/lldb/tools/lldb-dap/Breakpoint.cpp @@ -0,0 +1,182 @@ +//===-- Breakpoint.cpp ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Breakpoint.h" +#include "DAP.h" +#include "JSONUtils.h" +#include "llvm/ADT/StringExtras.h" + +using namespace lldb_dap; + +void Breakpoint::SetCondition() { bp.SetCondition(condition.c_str()); } + +void Breakpoint::SetHitCondition() { + uint64_t hitCount = 0; + if (llvm::to_integer(hitCondition, hitCount)) + bp.SetIgnoreCount(hitCount - 1); +} + +// logMessage will be divided into array of LogMessagePart as two kinds: +// 1. raw print text message, and +// 2. interpolated expression for evaluation which is inside matching curly +// braces. +// +// The function tries to parse logMessage into a list of LogMessageParts +// for easy later access in BreakpointHitCallback. +void Breakpoint::SetLogMessage() { + logMessageParts.clear(); + + // Contains unmatched open curly braces indices. + std::vector<int> unmatched_curly_braces; + + // Contains all matched curly braces in logMessage. + // Loop invariant: matched_curly_braces_ranges are sorted by start index in + // ascending order without any overlap between them. + std::vector<std::pair<int, int>> matched_curly_braces_ranges; + + lldb::SBError error; + // Part1 - parse matched_curly_braces_ranges. + // locating all curly braced expression ranges in logMessage. + // The algorithm takes care of nested and imbalanced curly braces. + for (size_t i = 0; i < logMessage.size(); ++i) { + if (logMessage[i] == '{') { + unmatched_curly_braces.push_back(i); + } else if (logMessage[i] == '}') { + if (unmatched_curly_braces.empty()) + // Nothing to match. + continue; + + int last_unmatched_index = unmatched_curly_braces.back(); + unmatched_curly_braces.pop_back(); + + // Erase any matched ranges included in the new match. + while (!matched_curly_braces_ranges.empty()) { + assert(matched_curly_braces_ranges.back().first != + last_unmatched_index && + "How can a curley brace be matched twice?"); + if (matched_curly_braces_ranges.back().first < last_unmatched_index) + break; + + // This is a nested range let's earse it. + assert((size_t)matched_curly_braces_ranges.back().second < i); + matched_curly_braces_ranges.pop_back(); + } + + // Assert invariant. + assert(matched_curly_braces_ranges.empty() || + matched_curly_braces_ranges.back().first < last_unmatched_index); + matched_curly_braces_ranges.emplace_back(last_unmatched_index, i); + } + } + + // Part2 - parse raw text and expresions parts. + // All expression ranges have been parsed in matched_curly_braces_ranges. + // The code below uses matched_curly_braces_ranges to divide logMessage + // into raw text parts and expression parts. + int last_raw_text_start = 0; + for (const std::pair<int, int> &curly_braces_range : + matched_curly_braces_ranges) { + // Raw text before open curly brace. + assert(curly_braces_range.first >= last_raw_text_start); + size_t raw_text_len = curly_braces_range.first - last_raw_text_start; + if (raw_text_len > 0) { + error = AppendLogMessagePart( + llvm::StringRef(logMessage.c_str() + last_raw_text_start, + raw_text_len), + /*is_expr=*/false); + if (error.Fail()) { + NotifyLogMessageError(error.GetCString()); + return; + } + } + + // Expression between curly braces. + assert(curly_braces_range.second > curly_braces_range.first); + size_t expr_len = curly_braces_range.second - curly_braces_range.first - 1; + error = AppendLogMessagePart( + llvm::StringRef(logMessage.c_str() + curly_braces_range.first + 1, + expr_len), + /*is_expr=*/true); + if (error.Fail()) { + NotifyLogMessageError(error.GetCString()); + return; + } + + last_raw_text_start = curly_braces_range.second + 1; + } + // Trailing raw text after close curly brace. + assert(last_raw_text_start >= 0); + if (logMessage.size() > (size_t)last_raw_text_start) { + error = AppendLogMessagePart( + llvm::StringRef(logMessage.c_str() + last_raw_text_start, + logMessage.size() - last_raw_text_start), + /*is_expr=*/false); + if (error.Fail()) { + NotifyLogMessageError(error.GetCString()); + return; + } + } + + bp.SetCallback(BreakpointBase::BreakpointHitCallback, this); +} + +void Breakpoint::CreateJsonObject(llvm::json::Object &object) { + // Each breakpoint location is treated as a separate breakpoint for VS code. + // They don't have the notion of a single breakpoint with multiple locations. + if (!bp.IsValid()) + return; + object.try_emplace("verified", bp.GetNumResolvedLocations() > 0); + object.try_emplace("id", bp.GetID()); + // VS Code DAP doesn't currently allow one breakpoint to have multiple + // locations so we just report the first one. If we report all locations + // then the IDE starts showing the wrong line numbers and locations for + // other source file and line breakpoints in the same file. + + // Below we search for the first resolved location in a breakpoint and report + // this as the breakpoint location since it will have a complete location + // that is at least loaded in the current process. + lldb::SBBreakpointLocation bp_loc; + const auto num_locs = bp.GetNumLocations(); + for (size_t i = 0; i < num_locs; ++i) { + bp_loc = bp.GetLocationAtIndex(i); + if (bp_loc.IsResolved()) + break; + } + // If not locations are resolved, use the first location. + if (!bp_loc.IsResolved()) + bp_loc = bp.GetLocationAtIndex(0); + auto bp_addr = bp_loc.GetAddress(); + + if (bp_addr.IsValid()) { + std::string formatted_addr = + "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(g_dap.target)); + object.try_emplace("instructionReference", formatted_addr); + auto line_entry = bp_addr.GetLineEntry(); + const auto line = line_entry.GetLine(); + if (line != UINT32_MAX) + object.try_emplace("line", line); + const auto column = line_entry.GetColumn(); + if (column != 0) + object.try_emplace("column", column); + object.try_emplace("source", CreateSource(line_entry)); + } +} + +bool Breakpoint::MatchesName(const char *name) { return bp.MatchesName(name); } + +void Breakpoint::SetBreakpoint() { + // See comments in BreakpointBase::GetBreakpointLabel() for details of why + // we add a label to our breakpoints. + bp.AddName(GetBreakpointLabel()); + if (!condition.empty()) + SetCondition(); + if (!hitCondition.empty()) + SetHitCondition(); + if (!logMessage.empty()) + SetLogMessage(); +} diff --git a/lldb/tools/lldb-dap/Breakpoint.h b/lldb/tools/lldb-dap/Breakpoint.h new file mode 100644 index 00000000000000..a668e29f3d1e8d --- /dev/null +++ b/lldb/tools/lldb-dap/Breakpoint.h @@ -0,0 +1,34 @@ +//===-- Breakpoint.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_TOOLS_LLDB_DAP_BREAKPOINT_H +#define LLDB_TOOLS_LLDB_DAP_BREAKPOINT_H + +#include "BreakpointBase.h" + +namespace lldb_dap { + +struct Breakpoint : public BreakpointBase { + // The LLDB breakpoint associated wit this source breakpoint + lldb::SBBreakpoint bp; + + Breakpoint() = default; + Breakpoint(const llvm::json::Object &obj) : BreakpointBase(obj){}; + Breakpoint(lldb::SBBreakpoint bp): bp(bp) {} + + void SetCondition() override; + void SetHitCondition() override; + void SetLogMessage() override; + void CreateJsonObject(llvm::json::Object &object) override; + + bool MatchesName(const char *name); + void SetBreakpoint(); +}; +} // namespace lldb_dap + +#endif diff --git a/lldb/tools/lldb-dap/BreakpointBase.cpp b/lldb/tools/lldb-dap/BreakpointBase.cpp index fb4b27fbe315fc..088ccc6b27f8e2 100644 --- a/lldb/tools/lldb-dap/BreakpointBase.cpp +++ b/lldb/tools/lldb-dap/BreakpointBase.cpp @@ -8,7 +8,6 @@ #include "BreakpointBase.h" #include "DAP.h" -#include "JSONUtils.h" #include "llvm/ADT/StringExtras.h" using namespace lldb_dap; @@ -18,14 +17,6 @@ BreakpointBase::BreakpointBase(const llvm::json::Object &obj) hitCondition(std::string(GetString(obj, "hitCondition"))), logMessage(std::string(GetString(obj, "logMessage"))) {} -void BreakpointBase::SetCondition() { bp.SetCondition(condition.c_str()); } - -void BreakpointBase::SetHitCondition() { - uint64_t hitCount = 0; - if (llvm::to_integer(hitCondition, hitCount)) - bp.SetIgnoreCount(hitCount - 1); -} - lldb::SBError BreakpointBase::AppendLogMessagePart(llvm::StringRef part, bool is_expr) { if (is_expr) { @@ -164,110 +155,6 @@ lldb::SBError BreakpointBase::FormatLogText(llvm::StringRef text, return error; } -// logMessage will be divided into array of LogMessagePart as two kinds: -// 1. raw print text message, and -// 2. interpolated expression for evaluation which is inside matching curly -// braces. -// -// The function tries to parse logMessage into a list of LogMessageParts -// for easy later access in BreakpointHitCallback. -void BreakpointBase::SetLogMessage() { - logMessageParts.clear(); - - // Contains unmatched open curly braces indices. - std::vector<int> unmatched_curly_braces; - - // Contains all matched curly braces in logMessage. - // Loop invariant: matched_curly_braces_ranges are sorted by start index in - // ascending order without any overlap between them. - std::vector<std::pair<int, int>> matched_curly_braces_ranges; - - lldb::SBError error; - // Part1 - parse matched_curly_braces_ranges. - // locating all curly braced expression ranges in logMessage. - // The algorithm takes care of nested and imbalanced curly braces. - for (size_t i = 0; i < logMessage.size(); ++i) { - if (logMessage[i] == '{') { - unmatched_curly_braces.push_back(i); - } else if (logMessage[i] == '}') { - if (unmatched_curly_braces.empty()) - // Nothing to match. - continue; - - int last_unmatched_index = unmatched_curly_braces.back(); - unmatched_curly_braces.pop_back(); - - // Erase any matched ranges included in the new match. - while (!matched_curly_braces_ranges.empty()) { - assert(matched_curly_braces_ranges.back().first != - last_unmatched_index && - "How can a curley brace be matched twice?"); - if (matched_curly_braces_ranges.back().first < last_unmatched_index) - break; - - // This is a nested range let's earse it. - assert((size_t)matched_curly_braces_ranges.back().second < i); - matched_curly_braces_ranges.pop_back(); - } - - // Assert invariant. - assert(matched_curly_braces_ranges.empty() || - matched_curly_braces_ranges.back().first < last_unmatched_index); - matched_curly_braces_ranges.emplace_back(last_unmatched_index, i); - } - } - - // Part2 - parse raw text and expresions parts. - // All expression ranges have been parsed in matched_curly_braces_ranges. - // The code below uses matched_curly_braces_ranges to divide logMessage - // into raw text parts and expression parts. - int last_raw_text_start = 0; - for (const std::pair<int, int> &curly_braces_range : - matched_curly_braces_ranges) { - // Raw text before open curly brace. - assert(curly_braces_range.first >= last_raw_text_start); - size_t raw_text_len = curly_braces_range.first - last_raw_text_start; - if (raw_text_len > 0) { - error = AppendLogMessagePart( - llvm::StringRef(logMessage.c_str() + last_raw_text_start, - raw_text_len), - /*is_expr=*/false); - if (error.Fail()) { - NotifyLogMessageError(error.GetCString()); - return; - } - } - - // Expression between curly braces. - assert(curly_braces_range.second > curly_braces_range.first); - size_t expr_len = curly_braces_range.second - curly_braces_range.first - 1; - error = AppendLogMessagePart( - llvm::StringRef(logMessage.c_str() + curly_braces_range.first + 1, - expr_len), - /*is_expr=*/true); - if (error.Fail()) { - NotifyLogMessageError(error.GetCString()); - return; - } - - last_raw_text_start = curly_braces_range.second + 1; - } - // Trailing raw text after close curly brace. - assert(last_raw_text_start >= 0); - if (logMessage.size() > (size_t)last_raw_text_start) { - error = AppendLogMessagePart( - llvm::StringRef(logMessage.c_str() + last_raw_text_start, - logMessage.size() - last_raw_text_start), - /*is_expr=*/false); - if (error.Fail()) { - NotifyLogMessageError(error.GetCString()); - return; - } - } - - bp.SetCallback(BreakpointBase::BreakpointHitCallback, this); -} - void BreakpointBase::NotifyLogMessageError(llvm::StringRef error) { std::string message = "Log message has error: "; message += error; diff --git a/lldb/tools/lldb-dap/BreakpointBase.h b/lldb/tools/lldb-dap/BreakpointBase.h index 41787f78610215..a4184bfe65d272 100644 --- a/lldb/tools/lldb-dap/BreakpointBase.h +++ b/lldb/tools/lldb-dap/BreakpointBase.h @@ -9,7 +9,6 @@ #ifndef LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H #define LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H -#include "JSONUtils.h" #include "lldb/API/SBBreakpoint.h" #include "llvm/Support/JSON.h" #include <string> @@ -35,15 +34,16 @@ struct BreakpointBase { // interpolated. std::string logMessage; std::vector<LogMessagePart> logMessageParts; - // The LLDB breakpoint associated wit this source breakpoint - lldb::SBBreakpoint bp; BreakpointBase() = default; BreakpointBase(const llvm::json::Object &obj); + virtual ~BreakpointBase() = default; + + virtual void SetCondition() = 0; + virtual void SetHitCondition() = 0; + virtual void SetLogMessage() = 0; + virtual void CreateJsonObject(llvm::json::Object &object) = 0; - void SetCondition(); - void SetHitCondition(); - void SetLogMessage(); void UpdateBreakpoint(const BreakpointBase &request_bp); // Format \param text and return formatted text in \param formatted. diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt index 554567eb3b0e23..f8c0e4ecf36c2f 100644 --- a/lldb/tools/lldb-dap/CMakeLists.txt +++ b/lldb/tools/lldb-dap/CMakeLists.txt @@ -24,6 +24,7 @@ tablegen(LLVM Options.inc -gen-opt-parser-defs) add_public_tablegen_target(LLDBDAPOptionsTableGen) add_lldb_tool(lldb-dap lldb-dap.cpp + Breakpoint.cpp BreakpointBase.cpp ExceptionBreakpoint.cpp FifoFiles.cpp diff --git a/lldb/tools/lldb-dap/FunctionBreakpoint.cpp b/lldb/tools/lldb-dap/FunctionBreakpoint.cpp index d4bdb976500ecd..21743bf908706d 100644 --- a/lldb/tools/lldb-dap/FunctionBreakpoint.cpp +++ b/lldb/tools/lldb-dap/FunctionBreakpoint.cpp @@ -12,21 +12,13 @@ namespace lldb_dap { FunctionBreakpoint::FunctionBreakpoint(const llvm::json::Object &obj) - : BreakpointBase(obj), functionName(std::string(GetString(obj, "name"))) {} + : Breakpoint(obj), functionName(std::string(GetString(obj, "name"))) {} void FunctionBreakpoint::SetBreakpoint() { if (functionName.empty()) return; bp = g_dap.target.BreakpointCreateByName(functionName.c_str()); - // See comments in BreakpointBase::GetBreakpointLabel() for details of why - // we add a label to our breakpoints. - bp.AddName(GetBreakpointLabel()); - if (!condition.empty()) - SetCondition(); - if (!hitCondition.empty()) - SetHitCondition(); - if (!logMessage.empty()) - SetLogMessage(); + Breakpoint::SetBreakpoint(); } } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/FunctionBreakpoint.h b/lldb/tools/lldb-dap/FunctionBreakpoint.h index fc23e94e128763..b15ff1931a6b22 100644 --- a/lldb/tools/lldb-dap/FunctionBreakpoint.h +++ b/lldb/tools/lldb-dap/FunctionBreakpoint.h @@ -9,11 +9,11 @@ #ifndef LLDB_TOOLS_LLDB_DAP_FUNCTIONBREAKPOINT_H #define LLDB_TOOLS_LLDB_DAP_FUNCTIONBREAKPOINT_H -#include "BreakpointBase.h" +#include "Breakpoint.h" namespace lldb_dap { -struct FunctionBreakpoint : public BreakpointBase { +struct FunctionBreakpoint : public Breakpoint { std::string functionName; FunctionBreakpoint() = default; diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp b/lldb/tools/lldb-dap/JSONUtils.cpp index a8b438d9d6df39..878449a91aa66a 100644 --- a/lldb/tools/lldb-dap/JSONUtils.cpp +++ b/lldb/tools/lldb-dap/JSONUtils.cpp @@ -364,54 +364,14 @@ llvm::json::Value CreateScope(const llvm::StringRef name, // }, // "required": [ "verified" ] // } -llvm::json::Value CreateBreakpoint(lldb::SBBreakpoint &bp, +llvm::json::Value CreateBreakpoint(BreakpointBase *bp, std::optional<llvm::StringRef> request_path, std::optional<uint32_t> request_line, std::optional<uint32_t> request_column) { - // Each breakpoint location is treated as a separate breakpoint for VS code. - // They don't have the notion of a single breakpoint with multiple locations. llvm::json::Object object; - if (!bp.IsValid()) - return llvm::json::Value(std::move(object)); - - object.try_emplace("verified", bp.GetNumResolvedLocations() > 0); - object.try_emplace("id", bp.GetID()); - // VS Code DAP doesn't currently allow one breakpoint to have multiple - // locations so we just report the first one. If we report all locations - // then the IDE starts showing the wrong line numbers and locations for - // other source file and line breakpoints in the same file. - - // Below we search for the first resolved location in a breakpoint and report - // this as the breakpoint location since it will have a complete location - // that is at least loaded in the current process. - lldb::SBBreakpointLocation bp_loc; - const auto num_locs = bp.GetNumLocations(); - for (size_t i = 0; i < num_locs; ++i) { - bp_loc = bp.GetLocationAtIndex(i); - if (bp_loc.IsResolved()) - break; - } - // If not locations are resolved, use the first location. - if (!bp_loc.IsResolved()) - bp_loc = bp.GetLocationAtIndex(0); - auto bp_addr = bp_loc.GetAddress(); - if (request_path) object.try_emplace("source", CreateSource(*request_path)); - - if (bp_addr.IsValid()) { - std::string formatted_addr = - "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(g_dap.target)); - object.try_emplace("instructionReference", formatted_addr); - auto line_entry = bp_addr.GetLineEntry(); - const auto line = line_entry.GetLine(); - if (line != UINT32_MAX) - object.try_emplace("line", line); - const auto column = line_entry.GetColumn(); - if (column != 0) - object.try_emplace("column", column); - object.try_emplace("source", CreateSource(line_entry)); - } + bp->CreateJsonObject(object); // We try to add request_line as a fallback if (request_line) object.try_emplace("line", *request_line); @@ -506,7 +466,7 @@ llvm::json::Value CreateModule(lldb::SBModule &module) { return llvm::json::Value(std::move(object)); } -void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints, +void AppendBreakpoint(BreakpointBase *bp, llvm::json::Array &breakpoints, std::optional<llvm::StringRef> request_path, std::optional<uint32_t> request_line) { breakpoints.emplace_back(CreateBreakpoint(bp, request_path, request_line)); diff --git a/lldb/tools/lldb-dap/JSONUtils.h b/lldb/tools/lldb-dap/JSONUtils.h index 62338548890c0c..1515f5ba2e5f4d 100644 --- a/lldb/tools/lldb-dap/JSONUtils.h +++ b/lldb/tools/lldb-dap/JSONUtils.h @@ -9,6 +9,7 @@ #ifndef LLDB_TOOLS_LLDB_DAP_JSONUTILS_H #define LLDB_TOOLS_LLDB_DAP_JSONUTILS_H +#include "BreakpointBase.h" #include "DAPForward.h" #include "lldb/API/SBModule.h" #include "llvm/ADT/StringRef.h" @@ -191,7 +192,7 @@ void FillResponse(const llvm::json::Object &request, /// provided by the setBreakpoints request are returned to the IDE as a /// fallback. void AppendBreakpoint( - lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints, + BreakpointBase *bp, llvm::json::Array &breakpoints, std::optional<llvm::StringRef> request_path = std::nullopt, std::optional<uint32_t> request_line = std::nullopt); @@ -223,7 +224,7 @@ void AppendBreakpoint( /// A "Breakpoint" JSON object with that follows the formal JSON /// definition outlined by Microsoft. llvm::json::Value -CreateBreakpoint(lldb::SBBreakpoint &bp, +CreateBreakpoint(BreakpointBase *bp, std::optional<llvm::StringRef> request_path = std::nullopt, std::optional<uint32_t> request_line = std::nullopt, std::optional<uint32_t> request_column = std::nullopt); diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp index 3bd83c0a6874de..87e5c7177ca65a 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp +++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp @@ -12,22 +12,14 @@ namespace lldb_dap { SourceBreakpoint::SourceBreakpoint(const llvm::json::Object &obj) - : BreakpointBase(obj), line(GetUnsigned(obj, "line", 0)), + : Breakpoint(obj), line(GetUnsigned(obj, "line", 0)), column(GetUnsigned(obj, "column", 0)) {} void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) { lldb::SBFileSpecList module_list; bp = g_dap.target.BreakpointCreateByLocation(source_path.str().c_str(), line, column, 0, module_list); - // See comments in BreakpointBase::GetBreakpointLabel() for details of why - // we add a label to our breakpoints. - bp.AddName(GetBreakpointLabel()); - if (!condition.empty()) - SetCondition(); - if (!hitCondition.empty()) - SetHitCondition(); - if (!logMessage.empty()) - SetLogMessage(); + Breakpoint::SetBreakpoint(); } } // namespace lldb_dap diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h index f4b54a44fc6875..0b26048b53acf7 100644 --- a/lldb/tools/lldb-dap/SourceBreakpoint.h +++ b/lldb/tools/lldb-dap/SourceBreakpoint.h @@ -9,17 +9,17 @@ #ifndef LLDB_TOOLS_LLDB_DAP_SOURCEBREAKPOINT_H #define LLDB_TOOLS_LLDB_DAP_SOURCEBREAKPOINT_H -#include "BreakpointBase.h" +#include "Breakpoint.h" #include "llvm/ADT/StringRef.h" namespace lldb_dap { -struct SourceBreakpoint : public BreakpointBase { +struct SourceBreakpoint : public Breakpoint { uint32_t line; ///< The source line of the breakpoint or logpoint uint32_t column; ///< An optional source column of the breakpoint - SourceBreakpoint() : BreakpointBase(), line(0), column(0) {} + SourceBreakpoint() : Breakpoint(), line(0), column(0) {} SourceBreakpoint(const llvm::json::Object &obj); // Set this breakpoint in LLDB as a new breakpoint diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp index 01494dcc7da00f..67022347e6d624 100644 --- a/lldb/tools/lldb-dap/lldb-dap.cpp +++ b/lldb/tools/lldb-dap/lldb-dap.cpp @@ -525,7 +525,8 @@ void EventThreadFunction() { if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) { auto event_type = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(event); - auto bp = lldb::SBBreakpoint::GetBreakpointFromEvent(event); + auto bp = + Breakpoint(lldb::SBBreakpoint::GetBreakpointFromEvent(event)); // If the breakpoint was originated from the IDE, it will have the // BreakpointBase::GetBreakpointLabel() label attached. Regardless // of wether the locations were added or removed, the breakpoint @@ -541,7 +542,7 @@ void EventThreadFunction() { // mapped. Note that CreateBreakpoint doesn't apply source mapping. // Besides, the current implementation of VSCode ignores the // "source" element of breakpoint events. - llvm::json::Value source_bp = CreateBreakpoint(bp); + llvm::json::Value source_bp = CreateBreakpoint(&bp); source_bp.getAsObject()->erase("source"); body.try_emplace("breakpoint", source_bp); @@ -2345,7 +2346,7 @@ void request_setBreakpoints(const llvm::json::Object &request) { existing_source_bps->second.find(src_bp.line); if (existing_bp != existing_source_bps->second.end()) { existing_bp->second.UpdateBreakpoint(src_bp); - AppendBreakpoint(existing_bp->second.bp, response_breakpoints, path, + AppendBreakpoint(&existing_bp->second, response_breakpoints, path, src_bp.line); continue; } @@ -2354,7 +2355,7 @@ void request_setBreakpoints(const llvm::json::Object &request) { g_dap.source_breakpoints[path][src_bp.line] = src_bp; SourceBreakpoint &new_bp = g_dap.source_breakpoints[path][src_bp.line]; new_bp.SetBreakpoint(path.data()); - AppendBreakpoint(new_bp.bp, response_breakpoints, path, new_bp.line); + AppendBreakpoint(&new_bp, response_breakpoints, path, new_bp.line); } } } @@ -2567,7 +2568,7 @@ void request_setFunctionBreakpoints(const llvm::json::Object &request) { // handled it here and we don't need to set a new breakpoint below. request_bps.erase(request_pos); // Add this breakpoint info to the response - AppendBreakpoint(pair.second.bp, response_breakpoints); + AppendBreakpoint(&pair.second, response_breakpoints); } } // Remove any breakpoints that are no longer in our list @@ -2581,7 +2582,7 @@ void request_setFunctionBreakpoints(const llvm::json::Object &request) { g_dap.function_breakpoints[pair.first()] = std::move(pair.second); FunctionBreakpoint &new_bp = g_dap.function_breakpoints[pair.first()]; new_bp.SetBreakpoint(); - AppendBreakpoint(new_bp.bp, response_breakpoints); + AppendBreakpoint(&new_bp, response_breakpoints); } llvm::json::Object body; @@ -3582,8 +3583,8 @@ void request__testGetTargetBreakpoints(const llvm::json::Object &request) { FillResponse(request, response); llvm::json::Array response_breakpoints; for (uint32_t i = 0; g_dap.target.GetBreakpointAtIndex(i).IsValid(); ++i) { - auto bp = g_dap.target.GetBreakpointAtIndex(i); - AppendBreakpoint(bp, response_breakpoints); + auto bp = Breakpoint(g_dap.target.GetBreakpointAtIndex(i)); + AppendBreakpoint(&bp, response_breakpoints); } llvm::json::Object body; body.try_emplace("breakpoints", std::move(response_breakpoints)); diff --git a/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn b/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn index d8292df8c0e74f..98c2068f6da291 100644 --- a/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn +++ b/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn @@ -38,6 +38,7 @@ executable("lldb-dap") { # FIXME: rpath/install_name stuff on macOS for framework on macOS sources = [ + "Breakpoint.cpp", "BreakpointBase.cpp", "DAP.cpp", "ExceptionBreakpoint.cpp", _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits