https://github.com/DrSergei updated 
https://github.com/llvm/llvm-project/pull/167237

>From 482c89dcee876a9d50b0ecc0a9e90482a2d9c94a Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <[email protected]>
Date: Sat, 8 Nov 2025 22:41:39 +0300
Subject: [PATCH 1/5] [lldb-dap] Add data breakpoints for bytes

---
 .../test/tools/lldb-dap/dap_server.py         | 20 ++++---
 .../TestDAP_setDataBreakpoints.py             | 52 +++++++++++++++++++
 .../DataBreakpointInfoRequestHandler.cpp      | 44 +++++++++++-----
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |  3 ++
 4 files changed, 100 insertions(+), 19 deletions(-)

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 ac550962cfb85..aaa6f76001aa3 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
@@ -1234,16 +1234,24 @@ def request_setFunctionBreakpoints(self, names, 
condition=None, hitCondition=Non
         return response
 
     def request_dataBreakpointInfo(
-        self, variablesReference, name, frameIndex=0, threadId=None
+        self, variablesReference, name, size=None, frameIndex=0, threadId=None
     ):
         stackFrame = self.get_stackFrame(frameIndex=frameIndex, 
threadId=threadId)
         if stackFrame is None:
             return []
-        args_dict = {
-            "variablesReference": variablesReference,
-            "name": name,
-            "frameId": stackFrame["id"],
-        }
+        args_dict = (
+            {
+                "variablesReference": variablesReference,
+                "name": name,
+                "frameId": stackFrame["id"],
+            }
+            if size is None
+            else {
+                "bytes": size,
+                "name": name,
+                "asAddress": True,
+            }
+        )
         command_dict = {
             "command": "dataBreakpointInfo",
             "type": "request",
diff --git 
a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
index a542a318050dd..7afc42f89ce55 100644
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -171,3 +171,55 @@ def test_functionality(self):
         self.continue_to_next_stop()
         x_val = self.dap_server.get_local_variable_value("x")
         self.assertEqual(x_val, "10")
+
+    @skipIfWindows
+    def test_bytes(self):
+        """Tests setting data breakpoints on memory range."""
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        source = "main.cpp"
+        first_loop_break_line = line_number(source, "// first loop breakpoint")
+        self.set_source_breakpoints(source, [first_loop_break_line])
+        self.continue_to_next_stop()
+        # Test write watchpoints on x, arr[2]
+        x = self.dap_server.get_local_variable("x")
+        response_x = self.dap_server.request_dataBreakpointInfo(
+            0, x["memoryReference"], 4
+        )
+        arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
+        response_arr_2 = self.dap_server.request_dataBreakpointInfo(
+            0, arr_2["memoryReference"], 4
+        )
+
+        # Test response from dataBreakpointInfo request.
+        self.assertEqual(
+            response_x["body"]["dataId"].split("/"), 
[x["memoryReference"][2:], "4"]
+        )
+        self.assertEqual(response_x["body"]["accessTypes"], self.accessTypes)
+        self.assertEqual(
+            response_arr_2["body"]["dataId"].split("/"),
+            [arr_2["memoryReference"][2:], "4"],
+        )
+        self.assertEqual(response_arr_2["body"]["accessTypes"], 
self.accessTypes)
+        dataBreakpoints = [
+            {"dataId": response_x["body"]["dataId"], "accessType": "write"},
+            {"dataId": response_arr_2["body"]["dataId"], "accessType": 
"write"},
+        ]
+        set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
+        self.assertEqual(
+            set_response["body"]["breakpoints"],
+            [{"verified": True}, {"verified": True}],
+        )
+
+        self.continue_to_next_stop()
+        x_val = self.dap_server.get_local_variable_value("x")
+        i_val = self.dap_server.get_local_variable_value("i")
+        self.assertEqual(x_val, "2")
+        self.assertEqual(i_val, "1")
+
+        self.continue_to_next_stop()
+        arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
+        i_val = self.dap_server.get_local_variable_value("i")
+        self.assertEqual(arr_2["value"], "42")
+        self.assertEqual(i_val, "2")
+        self.dap_server.request_setDataBreakpoint([])
diff --git a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
index 87b93fc999ecd..c55b165c6b783 100644
--- a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
@@ -16,6 +16,20 @@
 
 namespace lldb_dap {
 
+static bool CheckAddress(DAP &dap, lldb::addr_t load_addr) {
+  lldb::SBMemoryRegionInfo region;
+  lldb::SBError err =
+      dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region);
+  // Only lldb-server supports "qMemoryRegionInfo". So, don't fail this
+  // request if SBProcess::GetMemoryRegionInfo returns error.
+  if (err.Success()) {
+    if (!(region.IsReadable() || region.IsWritable())) {
+      return false;
+    }
+  }
+  return true;
+}
+
 /// Obtains information on a possible data breakpoint that could be set on an
 /// expression or variable. Clients should only call this request if the
 /// corresponding capability supportsDataBreakpoints is true.
@@ -23,7 +37,6 @@ llvm::Expected<protocol::DataBreakpointInfoResponseBody>
 DataBreakpointInfoRequestHandler::Run(
     const protocol::DataBreakpointInfoArguments &args) const {
   protocol::DataBreakpointInfoResponseBody response;
-  lldb::SBFrame frame = dap.GetLLDBFrame(args.frameId);
   lldb::SBValue variable = dap.variables.FindVariable(
       args.variablesReference.value_or(0), args.name);
   std::string addr, size;
@@ -43,7 +56,8 @@ DataBreakpointInfoRequestHandler::Run(
       addr = llvm::utohexstr(load_addr);
       size = llvm::utostr(byte_size);
     }
-  } else if (args.variablesReference.value_or(0) == 0 && frame.IsValid()) {
+  } else if (lldb::SBFrame frame = dap.GetLLDBFrame(args.frameId);
+             args.variablesReference.value_or(0) == 0 && frame.IsValid()) {
     lldb::SBValue value = frame.EvaluateExpression(args.name.c_str());
     if (value.GetError().Fail()) {
       lldb::SBError error = value.GetError();
@@ -58,17 +72,10 @@ DataBreakpointInfoRequestHandler::Run(
       if (data.IsValid()) {
         size = llvm::utostr(data.GetByteSize());
         addr = llvm::utohexstr(load_addr);
-        lldb::SBMemoryRegionInfo region;
-        lldb::SBError err =
-            dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region);
-        // Only lldb-server supports "qMemoryRegionInfo". So, don't fail this
-        // request if SBProcess::GetMemoryRegionInfo returns error.
-        if (err.Success()) {
-          if (!(region.IsReadable() || region.IsWritable())) {
-            is_data_ok = false;
-            response.description = "memory region for address " + addr +
-                                   " has no read or write permissions";
-          }
+        if (!CheckAddress(dap, load_addr)) {
+          is_data_ok = false;
+          response.description = "memory region for address " + addr +
+                                 " has no read or write permissions";
         }
       } else {
         is_data_ok = false;
@@ -76,6 +83,17 @@ DataBreakpointInfoRequestHandler::Run(
             "unable to get byte size for expression: " + args.name;
       }
     }
+  } else if (args.asAddress) {
+    size = llvm::utostr(args.bytes.value_or(1));
+    if (llvm::StringRef(args.name).starts_with("0x"))
+      addr = args.name.substr(2);
+    else
+      addr = llvm::utohexstr(std::stoull(args.name));
+    if (!CheckAddress(dap, std::stoull(addr, 0, 16))) {
+      is_data_ok = false;
+      response.description = "memory region for address " + addr +
+                             " has no read or write permissions";
+    }
   } else {
     is_data_ok = false;
     response.description = "variable not found: " + args.name;
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h 
b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index bc22133d92453..c9cafd33327a8 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -432,6 +432,9 @@ class DataBreakpointInfoRequestHandler
 public:
   using RequestHandler::RequestHandler;
   static llvm::StringLiteral GetCommand() { return "dataBreakpointInfo"; }
+  FeatureSet GetSupportedFeatures() const override {
+    return {protocol::eAdapterFeatureDataBreakpointBytes};
+  }
   llvm::Expected<protocol::DataBreakpointInfoResponseBody>
   Run(const protocol::DataBreakpointInfoArguments &args) const override;
 };

>From 36466ae461bb3fde20bc63f1570156ad4e1a6b4c Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <[email protected]>
Date: Mon, 10 Nov 2025 22:18:40 +0300
Subject: [PATCH 2/5] Fix review comments

---
 .../test/tools/lldb-dap/dap_server.py         | 20 +++++++------------
 .../DataBreakpointInfoRequestHandler.cpp      |  6 +++---
 2 files changed, 10 insertions(+), 16 deletions(-)

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 aaa6f76001aa3..1f31b800e2cd9 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
@@ -1239,19 +1239,13 @@ def request_dataBreakpointInfo(
         stackFrame = self.get_stackFrame(frameIndex=frameIndex, 
threadId=threadId)
         if stackFrame is None:
             return []
-        args_dict = (
-            {
-                "variablesReference": variablesReference,
-                "name": name,
-                "frameId": stackFrame["id"],
-            }
-            if size is None
-            else {
-                "bytes": size,
-                "name": name,
-                "asAddress": True,
-            }
-        )
+        args_dict = {"name": name}
+        if size is None:
+            args_dict["variablesReference"] = variablesReference
+            args_dict["frameId"] = stackFrame["id"]
+        else:
+            args_dict["asAddress"] = True
+            args_dict["bytes"] = size
         command_dict = {
             "command": "dataBreakpointInfo",
             "type": "request",
diff --git a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
index c55b165c6b783..850a490f6890b 100644
--- a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
@@ -16,7 +16,7 @@
 
 namespace lldb_dap {
 
-static bool CheckAddress(DAP &dap, lldb::addr_t load_addr) {
+static bool IsRW(DAP &dap, lldb::addr_t load_addr) {
   lldb::SBMemoryRegionInfo region;
   lldb::SBError err =
       dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region);
@@ -72,7 +72,7 @@ DataBreakpointInfoRequestHandler::Run(
       if (data.IsValid()) {
         size = llvm::utostr(data.GetByteSize());
         addr = llvm::utohexstr(load_addr);
-        if (!CheckAddress(dap, load_addr)) {
+        if (!IsRW(dap, load_addr)) {
           is_data_ok = false;
           response.description = "memory region for address " + addr +
                                  " has no read or write permissions";
@@ -89,7 +89,7 @@ DataBreakpointInfoRequestHandler::Run(
       addr = args.name.substr(2);
     else
       addr = llvm::utohexstr(std::stoull(args.name));
-    if (!CheckAddress(dap, std::stoull(addr, 0, 16))) {
+    if (!IsRW(dap, std::stoull(addr, 0, 16))) {
       is_data_ok = false;
       response.description = "memory region for address " + addr +
                              " has no read or write permissions";

>From b4ce53e84a13c3e64611ddf4ab2f83d8cdccdb34 Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <[email protected]>
Date: Mon, 24 Nov 2025 18:30:00 +0300
Subject: [PATCH 3/5] Fix comments

---
 .../DataBreakpointInfoRequestHandler.cpp      | 22 ++++++++++++-------
 lldb/tools/lldb-dap/JSONUtils.cpp             |  2 +-
 2 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
index 850a490f6890b..5be7092a31005 100644
--- a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
@@ -10,6 +10,7 @@
 #include "EventHelper.h"
 #include "Protocol/ProtocolTypes.h"
 #include "RequestHandler.h"
+#include "lldb/API/SBAddress.h"
 #include "lldb/API/SBMemoryRegionInfo.h"
 #include "llvm/ADT/StringExtras.h"
 #include <optional>
@@ -17,6 +18,8 @@
 namespace lldb_dap {
 
 static bool IsRW(DAP &dap, lldb::addr_t load_addr) {
+  if (!lldb::SBAddress(load_addr, dap.target).IsValid())
+    return false;
   lldb::SBMemoryRegionInfo region;
   lldb::SBError err =
       dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region);
@@ -84,15 +87,18 @@ DataBreakpointInfoRequestHandler::Run(
       }
     }
   } else if (args.asAddress) {
-    size = llvm::utostr(args.bytes.value_or(1));
-    if (llvm::StringRef(args.name).starts_with("0x"))
-      addr = args.name.substr(2);
-    else
-      addr = llvm::utohexstr(std::stoull(args.name));
-    if (!IsRW(dap, std::stoull(addr, 0, 16))) {
+    size = llvm::utostr(args.bytes.value_or(dap.target.GetAddressByteSize()));
+    lldb::addr_t load_addr;
+    if (llvm::StringRef(args.name).getAsInteger<lldb::addr_t>(0, load_addr)) {
       is_data_ok = false;
-      response.description = "memory region for address " + addr +
-                             " has no read or write permissions";
+      response.description = args.name + " is not a valid address";
+    } else {
+      addr = llvm::utohexstr(load_addr);
+      if (!IsRW(dap, load_addr)) {
+        is_data_ok = false;
+        response.description = "memory region for address " + addr +
+                               " has no read or write permissions";
+      }
     }
   } else {
     is_data_ok = false;
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 1a3a6701b194d..e6ae745a44a0e 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -678,7 +678,7 @@ llvm::json::Value CreateThreadStopped(DAP &dap, 
lldb::SBThread &thread,
   } break;
   case lldb::eStopReasonWatchpoint:
   case lldb::eStopReasonInstrumentation:
-    body.try_emplace("reason", "breakpoint");
+    body.try_emplace("reason", "data breakpoint");
     break;
   case lldb::eStopReasonProcessorTrace:
     body.try_emplace("reason", "processor trace");

>From 848e7a0261b5a93bbe9bc2bdedabd7ec7e25ae93 Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <[email protected]>
Date: Fri, 28 Nov 2025 13:05:30 +0300
Subject: [PATCH 4/5] Add watchpoint ids

---
 .../test/tools/lldb-dap/lldbdap_testcase.py   |  1 +
 .../TestDAP_setDataBreakpoints.py             | 73 +++++++++++--------
 lldb/tools/lldb-dap/JSONUtils.cpp             | 11 ++-
 lldb/tools/lldb-dap/Watchpoint.cpp            |  1 +
 4 files changed, 55 insertions(+), 31 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 71ca60ebe8d34..c7d302cc2dea2 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
@@ -169,6 +169,7 @@ def verify_breakpoint_hit(self, breakpoint_ids: 
List[Union[int, str]]):
                 if (
                     body["reason"] != "breakpoint"
                     and body["reason"] != "instruction breakpoint"
+                    and body["reason"] != "data breakpoint"
                 ):
                     continue
                 if "hitBreakpointIds" not in body:
diff --git 
a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py 
b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
index 7afc42f89ce55..df029ca16d667 100644
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
@@ -39,18 +39,21 @@ def test_duplicate_start_addresses(self):
             {"dataId": response_x["body"]["dataId"], "accessType": "write"},
         ]
         set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.assertEqual(
-            set_response["body"]["breakpoints"],
-            [{"verified": False}, {"verified": True}, {"verified": True}],
-        )
-
-        self.continue_to_next_stop()
+        breakpoints = set_response["body"]["breakpoints"]
+        self.assertEqual(len(breakpoints), 3)
+        self.assertFalse(breakpoints[0]["verified"])
+        self.assertTrue(breakpoints[1]["verified"])
+        self.assertTrue(breakpoints[2]["verified"])
+
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[2]["id"]])
         x_val = self.dap_server.get_local_variable_value("x")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(x_val, "2")
         self.assertEqual(i_val, "1")
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[1]["id"]])
         arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(arr_2["value"], "42")
@@ -79,18 +82,20 @@ def test_expression(self):
             {"dataId": response_arr_2["body"]["dataId"], "accessType": 
"write"},
         ]
         set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.assertEqual(
-            set_response["body"]["breakpoints"],
-            [{"verified": True}, {"verified": True}],
-        )
+        breakpoints = set_response["body"]["breakpoints"]
+        self.assertEqual(len(breakpoints), 2)
+        self.assertTrue(breakpoints[0]["verified"])
+        self.assertTrue(breakpoints[1]["verified"])
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[0]["id"]])
         x_val = self.dap_server.get_local_variable_value("x")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(x_val, "2")
         self.assertEqual(i_val, "1")
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[1]["id"]])
         arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(arr_2["value"], "42")
@@ -123,18 +128,20 @@ def test_functionality(self):
             {"dataId": response_arr_2["body"]["dataId"], "accessType": 
"write"},
         ]
         set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.assertEqual(
-            set_response["body"]["breakpoints"],
-            [{"verified": True}, {"verified": True}],
-        )
+        breakpoints = set_response["body"]["breakpoints"]
+        self.assertEqual(len(breakpoints), 2)
+        self.assertTrue(breakpoints[0]["verified"])
+        self.assertTrue(breakpoints[1]["verified"])
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[0]["id"]])
         x_val = self.dap_server.get_local_variable_value("x")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(x_val, "2")
         self.assertEqual(i_val, "1")
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[1]["id"]])
         arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(arr_2["value"], "42")
@@ -153,8 +160,11 @@ def test_functionality(self):
             }
         ]
         set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.assertEqual(set_response["body"]["breakpoints"], [{"verified": 
True}])
-        self.continue_to_next_stop()
+        breakpoints = set_response["body"]["breakpoints"]
+        self.assertEqual(len(breakpoints), 1)
+        self.assertTrue(breakpoints[0]["verified"])
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[0]["id"]])
         x_val = self.dap_server.get_local_variable_value("x")
         self.assertEqual(x_val, "3")
 
@@ -167,8 +177,11 @@ def test_functionality(self):
             }
         ]
         set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.assertEqual(set_response["body"]["breakpoints"], [{"verified": 
True}])
-        self.continue_to_next_stop()
+        breakpoints = set_response["body"]["breakpoints"]
+        self.assertEqual(len(breakpoints), 1)
+        self.assertTrue(breakpoints[0]["verified"])
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[0]["id"]])
         x_val = self.dap_server.get_local_variable_value("x")
         self.assertEqual(x_val, "10")
 
@@ -206,18 +219,20 @@ def test_bytes(self):
             {"dataId": response_arr_2["body"]["dataId"], "accessType": 
"write"},
         ]
         set_response = 
self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.assertEqual(
-            set_response["body"]["breakpoints"],
-            [{"verified": True}, {"verified": True}],
-        )
+        breakpoints = set_response["body"]["breakpoints"]
+        self.assertEqual(len(breakpoints), 2)
+        self.assertTrue(breakpoints[0]["verified"])
+        self.assertTrue(breakpoints[1]["verified"])
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[0]["id"]])
         x_val = self.dap_server.get_local_variable_value("x")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(x_val, "2")
         self.assertEqual(i_val, "1")
 
-        self.continue_to_next_stop()
+        self.dap_server.request_continue()
+        self.verify_breakpoint_hit([breakpoints[1]["id"]])
         arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
         i_val = self.dap_server.get_local_variable_value("i")
         self.assertEqual(arr_2["value"], "42")
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index e6ae745a44a0e..512c85c13310c 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -676,9 +676,16 @@ llvm::json::Value CreateThreadStopped(DAP &dap, 
lldb::SBThread &thread,
       EmplaceSafeString(body, "description", desc_str);
     }
   } break;
-  case lldb::eStopReasonWatchpoint:
-  case lldb::eStopReasonInstrumentation:
+  case lldb::eStopReasonWatchpoint: {
     body.try_emplace("reason", "data breakpoint");
+    lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(0);
+    std::vector<lldb::break_id_t> bp_ids = {bp_id};
+    body.try_emplace("hitBreakpointIds", llvm::json::Array(bp_ids));
+    EmplaceSafeString(body, "description",
+                      llvm::formatv("data breakpoint {0}", bp_id).str());
+  } break;
+  case lldb::eStopReasonInstrumentation:
+    body.try_emplace("reason", "breakpoint");
     break;
   case lldb::eStopReasonProcessorTrace:
     body.try_emplace("reason", "processor trace");
diff --git a/lldb/tools/lldb-dap/Watchpoint.cpp 
b/lldb/tools/lldb-dap/Watchpoint.cpp
index 0acc980890be8..e730e71c0dc31 100644
--- a/lldb/tools/lldb-dap/Watchpoint.cpp
+++ b/lldb/tools/lldb-dap/Watchpoint.cpp
@@ -45,6 +45,7 @@ protocol::Breakpoint Watchpoint::ToProtocolBreakpoint() {
       breakpoint.message = m_error.GetCString();
   } else {
     breakpoint.verified = true;
+    breakpoint.id = m_wp.GetID();
   }
 
   return breakpoint;

>From 4d5fdf70afa8d66b6f2d1895247e7856c9401127 Mon Sep 17 00:00:00 2001
From: Druzhkov Sergei <[email protected]>
Date: Fri, 28 Nov 2025 16:22:22 +0300
Subject: [PATCH 5/5] Rework error handling

---
 .../DataBreakpointInfoRequestHandler.cpp      | 23 +++++++++----------
 lldb/tools/lldb-dap/JSONUtils.cpp             |  4 ++--
 2 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
index 5be7092a31005..5d03905b88259 100644
--- a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
@@ -7,6 +7,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "DAP.h"
+#include "DAPError.h"
 #include "EventHelper.h"
 #include "Protocol/ProtocolTypes.h"
 #include "RequestHandler.h"
@@ -89,17 +90,12 @@ DataBreakpointInfoRequestHandler::Run(
   } else if (args.asAddress) {
     size = llvm::utostr(args.bytes.value_or(dap.target.GetAddressByteSize()));
     lldb::addr_t load_addr;
-    if (llvm::StringRef(args.name).getAsInteger<lldb::addr_t>(0, load_addr)) {
-      is_data_ok = false;
-      response.description = args.name + " is not a valid address";
-    } else {
-      addr = llvm::utohexstr(load_addr);
-      if (!IsRW(dap, load_addr)) {
-        is_data_ok = false;
-        response.description = "memory region for address " + addr +
-                               " has no read or write permissions";
-      }
-    }
+    if (llvm::StringRef(args.name).getAsInteger<lldb::addr_t>(0, load_addr))
+      return llvm::make_error<DAPError>(args.name + " is not a valid address");
+    addr = llvm::utohexstr(load_addr);
+    if (!IsRW(dap, load_addr))
+      return llvm::make_error<DAPError>("memory region for address " + addr +
+                                        " has no read or write permissions");
   } else {
     is_data_ok = false;
     response.description = "variable not found: " + args.name;
@@ -110,7 +106,10 @@ DataBreakpointInfoRequestHandler::Run(
     response.accessTypes = {protocol::eDataBreakpointAccessTypeRead,
                             protocol::eDataBreakpointAccessTypeWrite,
                             protocol::eDataBreakpointAccessTypeReadWrite};
-    response.description = size + " bytes at " + addr + " " + args.name;
+    if (args.asAddress)
+      response.description = size + " bytes at " + addr;
+    else
+      response.description = size + " bytes at " + addr + " " + args.name;
   }
 
   return response;
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 512c85c13310c..c730355dd0e9c 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -679,8 +679,8 @@ llvm::json::Value CreateThreadStopped(DAP &dap, 
lldb::SBThread &thread,
   case lldb::eStopReasonWatchpoint: {
     body.try_emplace("reason", "data breakpoint");
     lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(0);
-    std::vector<lldb::break_id_t> bp_ids = {bp_id};
-    body.try_emplace("hitBreakpointIds", llvm::json::Array(bp_ids));
+    body.try_emplace("hitBreakpointIds",
+                     llvm::json::Array{llvm::json::Value(bp_id)});
     EmplaceSafeString(body, "description",
                       llvm::formatv("data breakpoint {0}", bp_id).str());
   } break;

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to