[Lldb-commits] [lldb] [llvm] [lldb-dap] migrate set breakpoint requests (PR #137448)
Ely Ronnen via lldb-commits
lldb-commits at lists.llvm.org
Sat Apr 26 02:31:30 PDT 2025
https://github.com/eronnen updated https://github.com/llvm/llvm-project/pull/137448
>From d0d8c7e24fd7ee37f4a3678537df1e28c8318d04 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 26 Apr 2025 10:25:21 +0200
Subject: [PATCH 1/4] adding breakpoints protocol types
---
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 178 +++++++++++++++++++
llvm/include/llvm/Support/JSON.h | 8 +
2 files changed, 186 insertions(+)
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index 54941f24efbd9..8b193287acc19 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -322,6 +322,184 @@ enum SteppingGranularity : unsigned {
bool fromJSON(const llvm::json::Value &, SteppingGranularity &,
llvm::json::Path);
+/// Information about a breakpoint created in `setBreakpoints`, `setFunctionBreakpoints`, `setInstructionBreakpoints`, or `setDataBreakpoints` requests.
+struct Breakpoint {
+ /// A machine-readable explanation of why a breakpoint may not be verified.
+ enum class Reason : unsigned {
+ /// Indicates a breakpoint might be verified in the future, but
+ /// the adapter cannot verify it in the current state.
+ eBreakpointReasonPending,
+ /// Indicates a breakpoint was not able to be verified, and the
+ /// adapter does not believe it can be verified without intervention.
+ eBreakpointReasonFailed,
+ };
+
+ /// The identifier for the breakpoint. It is needed if breakpoint events are
+ /// used to update or remove breakpoints.
+ std::optional<int> id;
+
+ /// If true, the breakpoint could be set (but not necessarily at the desired
+ /// location).
+ bool verified;
+
+ /// A message about the state of the breakpoint.
+ /// This is shown to the user and can be used to explain why a breakpoint could
+ /// not be verified.
+ std::optional<std::string> message;
+
+ /// The source where the breakpoint is located.
+ std::optional<Source> source;
+
+ /// The start line of the actual range covered by the breakpoint.
+ std::optional<uint32_t> line;
+
+ /// Start position of the source range covered by the breakpoint. It is
+ /// measured in UTF-16 code units and the client capability `columnsStartAt1`
+ /// determines whether it is 0- or 1-based.
+ std::optional<uint32_t> column;
+
+ /// The end line of the actual range covered by the breakpoint.
+ std::optional<uint32_t> endLine;
+
+ /// End position of the source range covered by the breakpoint. It is measured
+ /// in UTF-16 code units and the client capability `columnsStartAt1` determines
+ /// whether it is 0- or 1-based.
+ /// If no end line is given, then the end column is assumed to be in the start
+ /// line.
+ std::optional<uint32_t> endColumn;
+
+ /// A memory reference to where the breakpoint is set.
+ std::optional<std::string> instructionReference;
+
+ /// The offset from the instruction reference.
+ /// This can be negative.
+ std::optional<int64_t> offset;
+
+ /// A machine-readable explanation of why a breakpoint may not be verified. If
+ /// a breakpoint is verified or a specific reason is not known, the adapter
+ /// should omit this property.
+ std::optional<Reason> reason;
+};
+llvm::json::Value toJSON(const Breakpoint &);
+
+/// Properties of a breakpoint or logpoint passed to the `setBreakpoints` request
+struct SourceBreakpoint {
+ /// The source line of the breakpoint or logpoint.
+ uint32_t line;
+
+ /// Start position within source line of the breakpoint or logpoint. It is
+ /// measured in UTF-16 code units and the client capability `columnsStartAt1`
+ /// determines whether it is 0- or 1-based.
+ std::optional<uint32_t> column;
+
+ /// The expression for conditional breakpoints.
+ /// It is only honored by a debug adapter if the corresponding capability
+ /// `supportsConditionalBreakpoints` is true.
+ std::optional<std::string> condition;
+
+ /// The expression that controls how many hits of the breakpoint are ignored.
+ /// The debug adapter is expected to interpret the expression as needed.
+ /// The attribute is only honored by a debug adapter if the corresponding
+ /// capability `supportsHitConditionalBreakpoints` is true.
+ /// If both this property and `condition` are specified, `hitCondition` should
+ /// be evaluated only if the `condition` is met, and the debug adapter should
+ /// stop only if both conditions are met.
+ std::optional<std::string> hitCondition;
+
+ /// If this attribute exists and is non-empty, the debug adapter must not
+ /// 'break' (stop)
+ /// but log the message instead. Expressions within `{}` are interpolated.
+ /// The attribute is only honored by a debug adapter if the corresponding
+ /// capability `supportsLogPoints` is true.
+ /// If either `hitCondition` or `condition` is specified, then the message
+ /// should only be logged if those conditions are met.
+ std::optional<std::string> logMessage;
+
+ /// The mode of this breakpoint. If defined, this must be one of the
+ /// `breakpointModes` the debug adapter advertised in its `Capabilities`.
+ std::optional<std::string> mode;
+};
+bool fromJSON(const llvm::json::Value &, SourceBreakpoint &,
+ llvm::json::Path);
+
+/// Properties of a breakpoint passed to the `setFunctionBreakpoints` request.
+struct FunctionBreakpoint {
+ /// The name of the function.
+ std::string name;
+
+ /// An expression for conditional breakpoints.
+ /// It is only honored by a debug adapter if the corresponding capability
+ /// `supportsConditionalBreakpoints` is true.
+ std::optional<std::string> condition;
+
+ /// An expression that controls how many hits of the breakpoint are ignored.
+ /// The debug adapter is expected to interpret the expression as needed.
+ /// The attribute is only honored by a debug adapter if the corresponding
+ /// capability `supportsHitConditionalBreakpoints` is true.
+ std::optional<std::string> hitCondition;
+};
+bool fromJSON(const llvm::json::Value &, FunctionBreakpoint &,
+ llvm::json::Path);
+
+/// This enumeration defines all possible access types for data breakpoints. Values: ‘read’, ‘write’, ‘readWrite’
+enum DataBreakpointAccessType : unsigned {
+ eDataBreakpointAccessTypeRead,
+ eDataBreakpointAccessTypeWrite,
+ eDataBreakpointAccessTypeReadWrite
+};
+bool fromJSON(const llvm::json::Value &, DataBreakpointAccessType &,
+ llvm::json::Path);
+
+/// Properties of a data breakpoint passed to the `setDataBreakpoints` request.
+struct DataBreakpointInfo {
+ /// An id representing the data. This id is returned from the
+ /// `dataBreakpointInfo` request.
+ std::string dataId;
+
+ /// The access type of the data.
+ std::optional<DataBreakpointAccessType> accessType;
+
+ /// An expression for conditional breakpoints.
+ std::optional<std::string> condition;
+
+ /// An expression that controls how many hits of the breakpoint are ignored.
+ /// The debug adapter is expected to interpret the expression as needed.
+ std::optional<std::string> hitCondition;
+};
+bool fromJSON(const llvm::json::Value &, DataBreakpointInfo &,
+ llvm::json::Path);
+
+/// Properties of a breakpoint passed to the `setInstructionBreakpoints` request
+struct InstructionBreakpoint {
+ /// The instruction reference of the breakpoint.
+ /// This should be a memory or instruction pointer reference from an
+ /// `EvaluateResponse`, `Variable`, `StackFrame`, `GotoTarget`, or
+ /// `Breakpoint`.
+ std::string instructionReference;
+
+ /// The offset from the instruction reference in bytes.
+ /// This can be negative.
+ std::optional<int64_t> offset;
+
+ /// An expression for conditional breakpoints.
+ /// It is only honored by a debug adapter if the corresponding capability
+ /// `supportsConditionalBreakpoints` is true.
+ std::optional<std::string> condition;
+
+ /// An expression that controls how many hits of the breakpoint are ignored.
+ /// The debug adapter is expected to interpret the expression as needed.
+ /// The attribute is only honored by a debug adapter if the corresponding
+ /// capability `supportsHitConditionalBreakpoints` is true.
+ std::optional<std::string> hitCondition;
+
+ /// The mode of this breakpoint. If defined, this must be one of the
+ /// `breakpointModes` the debug adapter advertised in its `Capabilities`.
+ std::optional<std::string> mode;
+};
+bool fromJSON(const llvm::json::Value &, InstructionBreakpoint &,
+ llvm::json::Path);
+
+
} // namespace lldb_dap::protocol
#endif
diff --git a/llvm/include/llvm/Support/JSON.h b/llvm/include/llvm/Support/JSON.h
index 7f7f5f6228763..f1f4f4db709dd 100644
--- a/llvm/include/llvm/Support/JSON.h
+++ b/llvm/include/llvm/Support/JSON.h
@@ -776,6 +776,14 @@ inline bool fromJSON(const Value &E, bool &Out, Path P) {
P.report("expected boolean");
return false;
}
+inline bool fromJSON(const Value &E, unsigned int &Out, Path P) {
+ if (auto S = E.getAsInteger()) {
+ Out = *S;
+ return true;
+ }
+ P.report("expected integer");
+ return false;
+}
inline bool fromJSON(const Value &E, uint64_t &Out, Path P) {
if (auto S = E.getAsUINT64()) {
Out = *S;
>From 2c39c99082df8429f45258c1c9911a9c8f858e3a Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 26 Apr 2025 10:45:37 +0200
Subject: [PATCH 2/4] add all breakpoint requests JSON types
---
.../lldb-dap/Protocol/ProtocolRequests.h | 85 +++++++++++++++++++
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 60 +++++++++++++
2 files changed, 145 insertions(+)
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index 33f93cc38799a..ae515bd186c76 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -377,6 +377,91 @@ bool fromJSON(const llvm::json::Value &, StepOutArguments &, llvm::json::Path);
/// body field is required.
using StepOutResponse = VoidResponse;
+/// Arguments for `setBreakpoints` request.
+struct SetBreakpointsArguments {
+ /// The source location of the breakpoints; either `source.path` or
+ /// `source.sourceReference` must be specified.
+ Source source;
+
+ /// The code locations of the breakpoints.
+ std::optional<std::vector<SourceBreakpoint>> breakpoints;
+
+ /// Deprecated: The code locations of the breakpoints.
+ std::optional<std::vector<uint32_t>> lines;
+
+ /// A value of true indicates that the underlying source has been modified
+ /// which results in new breakpoint locations.
+ std::optional<bool> sourceModified;
+};
+bool fromJSON(const llvm::json::Value &, SetBreakpointsArguments &,
+ llvm::json::Path);
+
+/// Response to `setBreakpoints` request.
+/// Returned is information about each breakpoint created by this request.
+/// This includes the actual code location and whether the breakpoint could be verified.
+/// The breakpoints returned are in the same order as the elements of the breakpoints
+/// (or the deprecated lines) array in the arguments.
+struct SetBreakpointsResponseBody {
+ /// Information about the breakpoints.
+ /// The array elements are in the same order as the elements of the
+ /// `breakpoints` (or the deprecated `lines`) array in the arguments.
+ std::vector<Breakpoint> breakpoints;
+};
+llvm::json::Value toJSON(const SetBreakpointsResponseBody &);
+
+/// Arguments for `setFunctionBreakpoints` request.
+struct SetFunctionBreakpointsArguments {
+ /// The function names of the breakpoints.
+ std::vector<FunctionBreakpoint> breakpoints;
+};
+bool fromJSON(const llvm::json::Value &, SetFunctionBreakpointsArguments &,
+ llvm::json::Path);
+
+/// Response to `setFunctionBreakpoints` request.
+/// Returned is information about each breakpoint created by this request.
+struct SetFunctionBreakpointsResponseBody {
+ /// Information about the breakpoints. The array elements correspond to the
+ /// elements of the `breakpoints` array.
+ std::vector<Breakpoint> breakpoints;
+};
+llvm::json::Value toJSON(const SetFunctionBreakpointsResponseBody &);
+
+/// Arguments for `setExceptionBreakpoints` request.
+struct SetExceptionBreakpointsArguments {
+ /// Set of exception filters specified by their ID. The set of all possible
+ /// exception filters is defined by the `exceptionBreakpointFilters`
+ /// capability. The `filter` and `filterOptions` sets are additive.
+ std::vector<std::string> filters;
+
+ /// Set of exception filters and their options. The set of all possible
+ /// exception filters is defined by the `exceptionBreakpointFilters`
+ /// capability. This attribute is only honored by a debug adapter if the
+ /// corresponding capability `supportsExceptionFilterOptions` is true. The
+ /// `filter` and `filterOptions` sets are additive.
+ std::optional<std::vector<ExceptionFilterOptions>> filterOptions;
+
+ /// Configuration options for selected exceptions.
+ /// The attribute is only honored by a debug adapter if the corresponding
+ /// capability `supportsExceptionOptions` is true.
+ std::optional<std::vector<ExceptionOptions>> exceptionOptions;
+};
+
+/// Arguments for `setInstructionBreakpoints` request.
+struct SetInstructionBreakpointsArguments {
+ /// The instruction references of the breakpoints.
+ std::vector<InstructionBreakpoint> breakpoints;
+};
+bool fromJSON(const llvm::json::Value &, SetInstructionBreakpointsArguments &,
+ llvm::json::Path);
+
+/// Response to `setInstructionBreakpoints` request.
+struct SetInstructionBreakpointsResponseBody {
+ /// Information about the breakpoints. The array elements correspond to the
+ /// elements of the `breakpoints` array.
+ std::vector<Breakpoint> breakpoints;
+};
+llvm::json::Value toJSON(const SetInstructionBreakpointsResponseBody &);
+
} // namespace lldb_dap::protocol
#endif
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index 8b193287acc19..f10adbac9e41c 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -499,6 +499,66 @@ struct InstructionBreakpoint {
bool fromJSON(const llvm::json::Value &, InstructionBreakpoint &,
llvm::json::Path);
+/// An ExceptionFilterOptions is used to specify an exception filter together with a condition for the `setExceptionBreakpoints` request.
+struct ExceptionFilterOptions {
+ /// ID of an exception filter returned by the `exceptionBreakpointFilters`
+ /// capability.
+ std::string filterId;
+
+ /// An expression for conditional exceptions.
+ /// The exception breaks into the debugger if the result of the condition is
+ /// true.
+ std::optional<std::string> condition;
+
+ /// The mode of this exception breakpoint. If defined, this must be one of the
+ /// `breakpointModes` the debug adapter advertised in its `Capabilities`.
+ std::optional<std::string> mode;
+};
+bool fromJSON(const llvm::json::Value &, ExceptionFilterOptions &,
+ llvm::json::Path);
+
+/// This enumeration defines all possible conditions when a thrown exception
+/// should result in a break.
+enum ExceptionBreakMode : unsigned {
+ /// Never breaks.
+ eExceptionBreakModeNever,
+ /// Always breaks.
+ eExceptionBreakModeAlways,
+ /// Breaks when the exception is unhandled.
+ eExceptionBreakModeUnhandled,
+ /// Breaks if the exception is not handled by user code.
+ eExceptionBreakModeUserUnhandled
+};
+bool fromJSON(const llvm::json::Value &, ExceptionBreakMode &,
+ llvm::json::Path);
+
+/// An ExceptionPathSegment represents a segment in a path that is used to
+/// match leafs or nodes in a tree of exceptions.
+struct ExceptionPathSegment {
+ /// If false or missing, this segment matches the names provided. Otherwise,
+ /// it matches anything except the names provided.
+ std::optional<bool> negate;
+
+ /// Depending on the value of `negate`, the names that should match or not
+ /// match.
+ std::vector<std::string> names;
+};
+bool fromJSON(const llvm::json::Value &, ExceptionPathSegment &,
+ llvm::json::Path);
+
+/// ExceptionOptions assigns configuration options to a set of exceptions.
+struct ExceptionOptions {
+ /// A path that selects a single or multiple exceptions in a tree. If `path`
+ /// is missing, the whole tree is selected.
+ /// By convention, the first segment of the path is a category that is used
+ /// to group exceptions in the UI.
+ std::optional<std::vector<ExceptionPathSegment>> path;
+
+ /// Condition when a thrown exception should result in a break.
+ ExceptionBreakMode breakMode;
+};
+bool fromJSON(const llvm::json::Value &, ExceptionOptions &,
+ llvm::json::Path);
} // namespace lldb_dap::protocol
>From a18da83181ad303ef344f88f61ea00a3306c3b23 Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 26 Apr 2025 11:12:31 +0200
Subject: [PATCH 3/4] decouple JSON from DAP Breakpoint classes
---
lldb/tools/lldb-dap/Breakpoint.h | 4 ++-
lldb/tools/lldb-dap/BreakpointBase.cpp | 10 +++---
lldb/tools/lldb-dap/BreakpointBase.h | 3 +-
lldb/tools/lldb-dap/FunctionBreakpoint.cpp | 8 ++---
lldb/tools/lldb-dap/FunctionBreakpoint.h | 3 +-
lldb/tools/lldb-dap/InstructionBreakpoint.cpp | 15 ++++----
lldb/tools/lldb-dap/InstructionBreakpoint.h | 4 ++-
.../lldb-dap/Protocol/ProtocolRequests.h | 6 ++--
lldb/tools/lldb-dap/Protocol/ProtocolTypes.h | 34 ++++++++++---------
lldb/tools/lldb-dap/SourceBreakpoint.cpp | 13 ++++---
lldb/tools/lldb-dap/SourceBreakpoint.h | 3 +-
11 files changed, 55 insertions(+), 48 deletions(-)
diff --git a/lldb/tools/lldb-dap/Breakpoint.h b/lldb/tools/lldb-dap/Breakpoint.h
index 580017125af44..987dbeadd4659 100644
--- a/lldb/tools/lldb-dap/Breakpoint.h
+++ b/lldb/tools/lldb-dap/Breakpoint.h
@@ -17,7 +17,9 @@ namespace lldb_dap {
class Breakpoint : public BreakpointBase {
public:
- Breakpoint(DAP &d, const llvm::json::Object &obj) : BreakpointBase(d, obj) {}
+ Breakpoint(DAP &d, const std::optional<std::string> &condition,
+ const std::optional<std::string> &hit_condition)
+ : BreakpointBase(d, condition, hit_condition) {}
Breakpoint(DAP &d, lldb::SBBreakpoint bp) : BreakpointBase(d), m_bp(bp) {}
lldb::break_id_t GetID() const { return m_bp.GetID(); }
diff --git a/lldb/tools/lldb-dap/BreakpointBase.cpp b/lldb/tools/lldb-dap/BreakpointBase.cpp
index 331ce8efee9bc..960dc5fc5ee56 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.cpp
+++ b/lldb/tools/lldb-dap/BreakpointBase.cpp
@@ -12,11 +12,11 @@
using namespace lldb_dap;
-BreakpointBase::BreakpointBase(DAP &d, const llvm::json::Object &obj)
- : m_dap(d),
- m_condition(std::string(GetString(obj, "condition").value_or(""))),
- m_hit_condition(
- std::string(GetString(obj, "hitCondition").value_or(""))) {}
+BreakpointBase::BreakpointBase(DAP &d,
+ const std::optional<std::string> &condition,
+ const std::optional<std::string> &hit_condition)
+ : m_dap(d), m_condition(condition.value_or("")),
+ m_hit_condition(hit_condition.value_or("")) {}
void BreakpointBase::UpdateBreakpoint(const BreakpointBase &request_bp) {
if (m_condition != request_bp.m_condition) {
diff --git a/lldb/tools/lldb-dap/BreakpointBase.h b/lldb/tools/lldb-dap/BreakpointBase.h
index 4c13326624831..e7aef44cc9d9a 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.h
+++ b/lldb/tools/lldb-dap/BreakpointBase.h
@@ -18,7 +18,8 @@ namespace lldb_dap {
class BreakpointBase {
public:
explicit BreakpointBase(DAP &d) : m_dap(d) {}
- BreakpointBase(DAP &d, const llvm::json::Object &obj);
+ BreakpointBase(DAP &d, const std::optional<std::string> &condition,
+ const std::optional<std::string> &hit_condition);
virtual ~BreakpointBase() = default;
virtual void SetCondition() = 0;
diff --git a/lldb/tools/lldb-dap/FunctionBreakpoint.cpp b/lldb/tools/lldb-dap/FunctionBreakpoint.cpp
index d87723f7557bd..1ea9cddb9f689 100644
--- a/lldb/tools/lldb-dap/FunctionBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/FunctionBreakpoint.cpp
@@ -8,15 +8,15 @@
#include "FunctionBreakpoint.h"
#include "DAP.h"
-#include "JSONUtils.h"
#include "lldb/API/SBMutex.h"
#include <mutex>
namespace lldb_dap {
-FunctionBreakpoint::FunctionBreakpoint(DAP &d, const llvm::json::Object &obj)
- : Breakpoint(d, obj),
- m_function_name(std::string(GetString(obj, "name").value_or(""))) {}
+FunctionBreakpoint::FunctionBreakpoint(
+ DAP &d, const protocol::FunctionBreakpoint &breakpoint)
+ : Breakpoint(d, breakpoint.condition, breakpoint.hitCondition),
+ m_function_name(breakpoint.name) {}
void FunctionBreakpoint::SetBreakpoint() {
lldb::SBMutex lock = m_dap.GetAPIMutex();
diff --git a/lldb/tools/lldb-dap/FunctionBreakpoint.h b/lldb/tools/lldb-dap/FunctionBreakpoint.h
index 7100360cd7ec1..76fbdb3e886a4 100644
--- a/lldb/tools/lldb-dap/FunctionBreakpoint.h
+++ b/lldb/tools/lldb-dap/FunctionBreakpoint.h
@@ -11,12 +11,13 @@
#include "Breakpoint.h"
#include "DAPForward.h"
+#include "Protocol/ProtocolTypes.h"
namespace lldb_dap {
class FunctionBreakpoint : public Breakpoint {
public:
- FunctionBreakpoint(DAP &dap, const llvm::json::Object &obj);
+ FunctionBreakpoint(DAP &dap, const protocol::FunctionBreakpoint &breakpoint);
/// Set this breakpoint in LLDB as a new breakpoint.
void SetBreakpoint();
diff --git a/lldb/tools/lldb-dap/InstructionBreakpoint.cpp b/lldb/tools/lldb-dap/InstructionBreakpoint.cpp
index dfdc6319ac9e8..ddae1a8b20243 100644
--- a/lldb/tools/lldb-dap/InstructionBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/InstructionBreakpoint.cpp
@@ -9,20 +9,19 @@
#include "InstructionBreakpoint.h"
#include "DAP.h"
-#include "JSONUtils.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBTarget.h"
#include "llvm/ADT/StringRef.h"
namespace lldb_dap {
-InstructionBreakpoint::InstructionBreakpoint(DAP &d,
- const llvm::json::Object &obj)
- : Breakpoint(d, obj), m_instruction_address_reference(LLDB_INVALID_ADDRESS),
- m_offset(GetInteger<int64_t>(obj, "offset").value_or(0)) {
- GetString(obj, "instructionReference")
- .value_or("")
- .getAsInteger(0, m_instruction_address_reference);
+InstructionBreakpoint::InstructionBreakpoint(
+ DAP &d, const protocol::InstructionBreakpoint &breakpoint)
+ : Breakpoint(d, breakpoint.condition, breakpoint.hitCondition),
+ m_instruction_address_reference(LLDB_INVALID_ADDRESS),
+ m_offset(breakpoint.offset.value_or(0)) {
+ llvm::StringRef instruction_reference(breakpoint.instructionReference);
+ instruction_reference.getAsInteger(0, m_instruction_address_reference);
m_instruction_address_reference += m_offset;
}
diff --git a/lldb/tools/lldb-dap/InstructionBreakpoint.h b/lldb/tools/lldb-dap/InstructionBreakpoint.h
index 6ed980e00d038..a8c8f2113e5eb 100644
--- a/lldb/tools/lldb-dap/InstructionBreakpoint.h
+++ b/lldb/tools/lldb-dap/InstructionBreakpoint.h
@@ -12,6 +12,7 @@
#include "Breakpoint.h"
#include "DAPForward.h"
+#include "Protocol/ProtocolTypes.h"
#include "lldb/lldb-types.h"
#include <cstdint>
@@ -20,7 +21,8 @@ namespace lldb_dap {
/// Instruction Breakpoint
class InstructionBreakpoint : public Breakpoint {
public:
- InstructionBreakpoint(DAP &d, const llvm::json::Object &obj);
+ InstructionBreakpoint(DAP &d,
+ const protocol::InstructionBreakpoint &breakpoint);
/// Set instruction breakpoint in LLDB as a new breakpoint.
void SetBreakpoint();
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index ae515bd186c76..b1a395ec4ae3d 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -398,9 +398,9 @@ bool fromJSON(const llvm::json::Value &, SetBreakpointsArguments &,
/// Response to `setBreakpoints` request.
/// Returned is information about each breakpoint created by this request.
-/// This includes the actual code location and whether the breakpoint could be verified.
-/// The breakpoints returned are in the same order as the elements of the breakpoints
-/// (or the deprecated lines) array in the arguments.
+/// This includes the actual code location and whether the breakpoint could be
+/// verified. The breakpoints returned are in the same order as the elements of
+/// the breakpoints (or the deprecated lines) array in the arguments.
struct SetBreakpointsResponseBody {
/// Information about the breakpoints.
/// The array elements are in the same order as the elements of the
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
index f10adbac9e41c..216dcd907ae15 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolTypes.h
@@ -322,7 +322,9 @@ enum SteppingGranularity : unsigned {
bool fromJSON(const llvm::json::Value &, SteppingGranularity &,
llvm::json::Path);
-/// Information about a breakpoint created in `setBreakpoints`, `setFunctionBreakpoints`, `setInstructionBreakpoints`, or `setDataBreakpoints` requests.
+/// Information about a breakpoint created in `setBreakpoints`,
+/// `setFunctionBreakpoints`, `setInstructionBreakpoints`, or
+/// `setDataBreakpoints` requests.
struct Breakpoint {
/// A machine-readable explanation of why a breakpoint may not be verified.
enum class Reason : unsigned {
@@ -343,8 +345,8 @@ struct Breakpoint {
bool verified;
/// A message about the state of the breakpoint.
- /// This is shown to the user and can be used to explain why a breakpoint could
- /// not be verified.
+ /// This is shown to the user and can be used to explain why a breakpoint
+ /// could not be verified.
std::optional<std::string> message;
/// The source where the breakpoint is located.
@@ -362,10 +364,9 @@ struct Breakpoint {
std::optional<uint32_t> endLine;
/// End position of the source range covered by the breakpoint. It is measured
- /// in UTF-16 code units and the client capability `columnsStartAt1` determines
- /// whether it is 0- or 1-based.
- /// If no end line is given, then the end column is assumed to be in the start
- /// line.
+ /// in UTF-16 code units and the client capability `columnsStartAt1`
+ /// determines whether it is 0- or 1-based. If no end line is given, then the
+ /// end column is assumed to be in the start line.
std::optional<uint32_t> endColumn;
/// A memory reference to where the breakpoint is set.
@@ -373,7 +374,7 @@ struct Breakpoint {
/// The offset from the instruction reference.
/// This can be negative.
- std::optional<int64_t> offset;
+ std::optional<int32_t> offset;
/// A machine-readable explanation of why a breakpoint may not be verified. If
/// a breakpoint is verified or a specific reason is not known, the adapter
@@ -382,7 +383,8 @@ struct Breakpoint {
};
llvm::json::Value toJSON(const Breakpoint &);
-/// Properties of a breakpoint or logpoint passed to the `setBreakpoints` request
+/// Properties of a breakpoint or logpoint passed to the `setBreakpoints`
+/// request
struct SourceBreakpoint {
/// The source line of the breakpoint or logpoint.
uint32_t line;
@@ -419,8 +421,7 @@ struct SourceBreakpoint {
/// `breakpointModes` the debug adapter advertised in its `Capabilities`.
std::optional<std::string> mode;
};
-bool fromJSON(const llvm::json::Value &, SourceBreakpoint &,
- llvm::json::Path);
+bool fromJSON(const llvm::json::Value &, SourceBreakpoint &, llvm::json::Path);
/// Properties of a breakpoint passed to the `setFunctionBreakpoints` request.
struct FunctionBreakpoint {
@@ -441,7 +442,8 @@ struct FunctionBreakpoint {
bool fromJSON(const llvm::json::Value &, FunctionBreakpoint &,
llvm::json::Path);
-/// This enumeration defines all possible access types for data breakpoints. Values: ‘read’, ‘write’, ‘readWrite’
+/// This enumeration defines all possible access types for data breakpoints.
+/// Values: ‘read’, ‘write’, ‘readWrite’
enum DataBreakpointAccessType : unsigned {
eDataBreakpointAccessTypeRead,
eDataBreakpointAccessTypeWrite,
@@ -479,7 +481,7 @@ struct InstructionBreakpoint {
/// The offset from the instruction reference in bytes.
/// This can be negative.
- std::optional<int64_t> offset;
+ std::optional<int32_t> offset;
/// An expression for conditional breakpoints.
/// It is only honored by a debug adapter if the corresponding capability
@@ -499,7 +501,8 @@ struct InstructionBreakpoint {
bool fromJSON(const llvm::json::Value &, InstructionBreakpoint &,
llvm::json::Path);
-/// An ExceptionFilterOptions is used to specify an exception filter together with a condition for the `setExceptionBreakpoints` request.
+/// An ExceptionFilterOptions is used to specify an exception filter together
+/// with a condition for the `setExceptionBreakpoints` request.
struct ExceptionFilterOptions {
/// ID of an exception filter returned by the `exceptionBreakpointFilters`
/// capability.
@@ -557,8 +560,7 @@ struct ExceptionOptions {
/// Condition when a thrown exception should result in a break.
ExceptionBreakMode breakMode;
};
-bool fromJSON(const llvm::json::Value &, ExceptionOptions &,
- llvm::json::Path);
+bool fromJSON(const llvm::json::Value &, ExceptionOptions &, llvm::json::Path);
} // namespace lldb_dap::protocol
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.cpp b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
index a7e00cae36fbc..4581c995b4260 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.cpp
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.cpp
@@ -26,13 +26,12 @@
namespace lldb_dap {
-SourceBreakpoint::SourceBreakpoint(DAP &dap, const llvm::json::Object &obj)
- : Breakpoint(dap, obj),
- m_log_message(GetString(obj, "logMessage").value_or("").str()),
- m_line(
- GetInteger<uint64_t>(obj, "line").value_or(LLDB_INVALID_LINE_NUMBER)),
- m_column(GetInteger<uint64_t>(obj, "column")
- .value_or(LLDB_INVALID_COLUMN_NUMBER)) {}
+SourceBreakpoint::SourceBreakpoint(DAP &dap,
+ const protocol::SourceBreakpoint &breakpoint)
+ : Breakpoint(dap, breakpoint.condition, breakpoint.hitCondition),
+ m_log_message(breakpoint.logMessage.value_or("")),
+ 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();
diff --git a/lldb/tools/lldb-dap/SourceBreakpoint.h b/lldb/tools/lldb-dap/SourceBreakpoint.h
index d01411547d12a..5b15296f861c5 100644
--- a/lldb/tools/lldb-dap/SourceBreakpoint.h
+++ b/lldb/tools/lldb-dap/SourceBreakpoint.h
@@ -11,6 +11,7 @@
#include "Breakpoint.h"
#include "DAPForward.h"
+#include "Protocol/ProtocolTypes.h"
#include "lldb/API/SBError.h"
#include "llvm/ADT/StringRef.h"
#include <cstdint>
@@ -21,7 +22,7 @@ namespace lldb_dap {
class SourceBreakpoint : public Breakpoint {
public:
- SourceBreakpoint(DAP &d, const llvm::json::Object &obj);
+ SourceBreakpoint(DAP &d, const protocol::SourceBreakpoint &breakpoint);
// Set this breakpoint in LLDB as a new breakpoint
void SetBreakpoint(const llvm::StringRef source_path);
>From b7b2454540a1b6f95c2b142768eaaa59bc6be68b Mon Sep 17 00:00:00 2001
From: Ely Ronnen <elyronnen at gmail.com>
Date: Sat, 26 Apr 2025 11:23:51 +0200
Subject: [PATCH 4/4] forgor exception breakpoint response
---
lldb/tools/lldb-dap/BreakpointBase.h | 2 +-
.../lldb-dap/Protocol/ProtocolRequests.h | 110 ++++++++++++++++++
2 files changed, 111 insertions(+), 1 deletion(-)
diff --git a/lldb/tools/lldb-dap/BreakpointBase.h b/lldb/tools/lldb-dap/BreakpointBase.h
index e7aef44cc9d9a..44f3bfa15afc3 100644
--- a/lldb/tools/lldb-dap/BreakpointBase.h
+++ b/lldb/tools/lldb-dap/BreakpointBase.h
@@ -10,7 +10,7 @@
#define LLDB_TOOLS_LLDB_DAP_BREAKPOINTBASE_H
#include "DAPForward.h"
-#include "llvm/ADT/StringRef.h"
+#include <optional>
#include <string>
namespace lldb_dap {
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
index b1a395ec4ae3d..7bcb8212575f4 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.h
@@ -445,6 +445,34 @@ struct SetExceptionBreakpointsArguments {
/// capability `supportsExceptionOptions` is true.
std::optional<std::vector<ExceptionOptions>> exceptionOptions;
};
+bool fromJSON(const llvm::json::Value &, SetExceptionBreakpointsArguments &,
+ llvm::json::Path);
+
+/// Response to `setExceptionBreakpoints` request.
+/// The response contains an array of Breakpoint objects with information about
+/// each exception breakpoint or filter. The Breakpoint objects are in the same
+/// order as the elements of the filters, filterOptions, exceptionOptions arrays
+/// given as arguments. If both filters and filterOptions are given, the
+/// returned array must start with filters information first, followed by
+/// filterOptions information.
+/// The verified property of a Breakpoint object signals whether the exception
+/// breakpoint or filter could be successfully created and whether the condition
+/// is valid. In case of an error the message property explains the problem. The
+/// id property can be used to introduce a unique ID for the exception
+/// breakpoint or filter so that it can be updated subsequently by sending
+/// breakpoint events. For backward compatibility both the breakpoints array and
+/// the enclosing body are optional. If these elements are missing a client is
+/// not able to show problems for individual exception breakpoints or filters.
+struct SetExceptionBreakpointsResponseBody {
+ /// Information about the exception breakpoints or filters.
+ /// The breakpoints returned are in the same order as the elements of the
+ /// `filters`, `filterOptions`, `exceptionOptions` arrays in the arguments.
+ /// If both `filters` and `filterOptions` are given, the returned array must
+ /// start with `filters` information first, followed by `filterOptions`
+ /// information.
+ std::vector<Breakpoint> breakpoints;
+};
+llvm::json::Value toJSON(const SetExceptionBreakpointsResponseBody &);
/// Arguments for `setInstructionBreakpoints` request.
struct SetInstructionBreakpointsArguments {
@@ -462,6 +490,88 @@ struct SetInstructionBreakpointsResponseBody {
};
llvm::json::Value toJSON(const SetInstructionBreakpointsResponseBody &);
+/// Arguments for `dataBreakpointInfo` request.
+struct DataBreakpointInfoArguments {
+ /// Reference to the variable container if the data breakpoint is requested
+ /// for a child of the container. The `variablesReference` must have been
+ /// obtained in the current suspended state.See 'Lifetime of Object
+ /// References' in the Overview section for details.
+ std::optional<int64_t> variablesReference;
+
+ /// The name of the variable's child to obtain data breakpoint information
+ /// for. If `variablesReference` isn't specified, this can be an expression,
+ /// or an address if `asAddress` is also true.
+ std::string name;
+
+ /// When `name` is an expression, evaluate it in the scope of this stack
+ /// frame. If not specified, the expression is evaluated in the global scope.
+ /// When `asAddress` is true, the `frameId` is ignored.
+ std::optional<int64_t> frameId;
+
+ /// If specified, a debug adapter should return information for the range of
+ /// memory extending `bytes` number of bytes from the address or variable
+ /// specified by `name`. Breakpoints set using the resulting data ID should
+ /// pause on data access anywhere within that range.
+ /// Clients may set this property only if the `supportsDataBreakpointBytes`
+ /// capability is true.
+ std::optional<int64_t> bytes;
+
+ /// If `true`, the `name` is a memory address and the debugger should
+ /// interpret it as a decimal value, or hex value if it is prefixed with `0x`.
+ /// Clients may set this property only if the `supportsDataBreakpointBytes`
+ /// capability is true.
+ std::optional<bool> asAddress;
+
+ /// The mode of the desired breakpoint. If defined, this must be one of the
+ /// `breakpointModes` the debug adapter advertised in its `Capabilities`.
+ std::optional<std::string> mode;
+};
+bool fromJSON(const llvm::json::Value &, DataBreakpointInfoArguments &,
+ llvm::json::Path);
+
+/// Response to `dataBreakpointInfo` request.
+struct DataBreakpointInfoResponseBody {
+ /// An identifier for the data on which a data breakpoint can be registered
+ /// with the `setDataBreakpoints` request or null if no data breakpoint is
+ /// available. If a `variablesReference` or `frameId` is passed, the `dataId`
+ /// is valid in the current suspended state, otherwise it's valid
+ /// indefinitely. See 'Lifetime of Object References' in the Overview section
+ /// for details. Breakpoints set using the `dataId` in the
+ /// `setDataBreakpoints` request may outlive the lifetime of the associated
+ /// `dataId`.
+ std::optional<std::string> dataId;
+
+ /// UI string that describes on what data the breakpoint is set on or why a
+ /// data breakpoint is not available.
+ std::string description;
+
+ /// Attribute lists the available access types for a potential data
+ /// breakpoint. A UI client could surface this information.
+ std::optional<std::vector<DataBreakpointAccessType>> accessTypes;
+
+ /// Attribute indicates that a potential data breakpoint could be persisted
+ /// across sessions.
+ std::optional<bool> canPersist;
+};
+llvm::json::Value toJSON(const DataBreakpointInfoResponseBody &);
+
+/// Arguments for `setDataBreakpoints` request.
+struct SetDataBreakpointsArguments {
+ /// The contents of this array replaces all existing data breakpoints. An
+ /// empty array clears all data breakpoints.
+ std::vector<DataBreakpointInfo> breakpoints;
+};
+bool fromJSON(const llvm::json::Value &, SetDataBreakpointsArguments &,
+ llvm::json::Path);
+
+/// Response to `setDataBreakpoints` request.
+struct SetDataBreakpointsResponseBody {
+ /// Information about the data breakpoints. The array elements correspond to
+ /// the elements of the input argument `breakpoints` array.
+ std::vector<Breakpoint> breakpoints;
+};
+llvm::json::Value toJSON(const SetDataBreakpointsResponseBody &);
+
} // namespace lldb_dap::protocol
#endif
More information about the lldb-commits
mailing list