[lldb] [llvm] Revert "[lldb-dap] Add support for data breakpoint. (#81541)" (PR #81812)

via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 14 17:24:29 PST 2024


https://github.com/Prabhuk created https://github.com/llvm/llvm-project/pull/81812

This reverts commit 8c56e78ec531f0e2460213c20fff869b6b7add99.

Reverting to address the LLDB test failure in ARM64.

>From 73070214069c491623689858788b4c26e434a10b Mon Sep 17 00:00:00 2001
From: prabhukr <prabhukr at google.com>
Date: Wed, 14 Feb 2024 17:21:07 -0800
Subject: [PATCH] Revert "[lldb-dap] Add support for data breakpoint. (#81541)"

This reverts commit 8c56e78ec531f0e2460213c20fff869b6b7add99.

Reverting to address the LLDB test failure in ARM64.
---
 .../test/tools/lldb-dap/dap_server.py         |  47 ---
 .../tools/lldb-dap/databreakpoint/Makefile    |   3 -
 .../TestDAP_setDataBreakpoints.py             | 123 -------
 .../tools/lldb-dap/databreakpoint/main.cpp    |  17 -
 lldb/tools/lldb-dap/CMakeLists.txt            |   1 -
 lldb/tools/lldb-dap/DAPForward.h              |   2 -
 lldb/tools/lldb-dap/Watchpoint.cpp            |  48 ---
 lldb/tools/lldb-dap/Watchpoint.h              |  34 --
 lldb/tools/lldb-dap/lldb-dap.cpp              | 307 ++----------------
 .../gn/secondary/lldb/tools/lldb-dap/BUILD.gn |   1 -
 10 files changed, 34 insertions(+), 549 deletions(-)
 delete mode 100644 lldb/test/API/tools/lldb-dap/databreakpoint/Makefile
 delete mode 100644 lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
 delete mode 100644 lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp
 delete mode 100644 lldb/tools/lldb-dap/Watchpoint.cpp
 delete mode 100644 lldb/tools/lldb-dap/Watchpoint.h

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 27a76a652f4063..bb863bb8719176 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
@@ -501,18 +501,6 @@ def get_local_variable_value(self, name, frameIndex=0, threadId=None):
             return variable["value"]
         return None
 
-    def get_local_variable_child(self, name, child_name, frameIndex=0, threadId=None):
-        local = self.get_local_variable(name, frameIndex, threadId)
-        if local["variablesReference"] == 0:
-            return None
-        children = self.request_variables(local["variablesReference"])["body"][
-            "variables"
-        ]
-        for child in children:
-            if child["name"] == child_name:
-                return child
-        return None
-
     def replay_packets(self, replay_file_path):
         f = open(replay_file_path, "r")
         mode = "invalid"
@@ -907,41 +895,6 @@ def request_setFunctionBreakpoints(self, names, condition=None, hitCondition=Non
         }
         return self.send_recv(command_dict)
 
-    def request_dataBreakpointInfo(
-        self, variablesReference, name, 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"],
-        }
-        command_dict = {
-            "command": "dataBreakpointInfo",
-            "type": "request",
-            "arguments": args_dict,
-        }
-        return self.send_recv(command_dict)
-
-    def request_setDataBreakpoint(self, dataBreakpoints):
-        """dataBreakpoints is a list of dictionary with following fields:
-        {
-            dataId: (address in hex)/(size in bytes)
-            accessType: read/write/readWrite
-            [condition]: string
-            [hitCondition]: string
-        }
-        """
-        args_dict = {"breakpoints": dataBreakpoints}
-        command_dict = {
-            "command": "setDataBreakpoints",
-            "type": "request",
-            "arguments": args_dict,
-        }
-        return self.send_recv(command_dict)
-
     def request_compileUnits(self, moduleId):
         args_dict = {"moduleId": moduleId}
         command_dict = {
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/Makefile b/lldb/test/API/tools/lldb-dap/databreakpoint/Makefile
deleted file mode 100644
index 99998b20bcb050..00000000000000
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-CXX_SOURCES := main.cpp
-
-include Makefile.rules
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py b/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
deleted file mode 100644
index 40ca6473649ea9..00000000000000
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/TestDAP_setDataBreakpoints.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""
-Test lldb-dap dataBreakpointInfo and setDataBreakpoints requests
-"""
-
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-import lldbdap_testcase
-
-
-class TestDAP_setDataBreakpoints(lldbdap_testcase.DAPTestCaseBase):
-    def setUp(self):
-        lldbdap_testcase.DAPTestCaseBase.setUp(self)
-        self.accessTypes = ["read", "write", "readWrite"]
-
-    @skipIfWindows
-    @skipIfRemote
-    def test_expression(self):
-        """Tests setting data breakpoints on expression."""
-        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()
-        self.dap_server.get_stackFrame()
-        # Test setting write watchpoint using expressions: &x, arr+2
-        response_x = self.dap_server.request_dataBreakpointInfo(0, "4@&x")
-        response_arr_2 = self.dap_server.request_dataBreakpointInfo(0, "1 at arr+2")
-        # Test response from dataBreakpointInfo request.
-        self.assertEquals(response_x["body"]["dataId"].split("/")[1], "4")
-        self.assertEquals(response_x["body"]["accessTypes"], self.accessTypes)
-        self.assertEquals(response_arr_2["body"]["dataId"].split("/")[1], "1")
-        self.assertEquals(response_arr_2["body"]["accessTypes"], self.accessTypes)
-        dataBreakpoints = [
-            {"dataId": response_x["body"]["dataId"], "accessType": "write"},
-            {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
-        ]
-        self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-
-        self.dap_server.request_continue()
-        self.dap_server.wait_for_stopped()
-        x_val = self.dap_server.get_local_variable_value("x")
-        i_val = self.dap_server.get_local_variable_value("i")
-        self.assertEquals(x_val, "2")
-        self.assertEquals(i_val, "1")
-
-        self.dap_server.request_continue()
-        self.dap_server.wait_for_stopped()
-        arr_2 = self.dap_server.get_local_variable_child("arr", "[2]")
-        i_val = self.dap_server.get_local_variable_value("i")
-        self.assertEquals(arr_2["value"], "'z'")
-        self.assertEquals(i_val, "2")
-
-    @skipIfWindows
-    @skipIfRemote
-    def test_functionality(self):
-        """Tests setting data breakpoints on variable."""
-        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()
-        self.dap_server.get_local_variables()
-        # Test write watchpoints on x, arr[2]
-        response_x = self.dap_server.request_dataBreakpointInfo(1, "x")
-        arr = self.dap_server.get_local_variable("arr")
-        response_arr_2 = self.dap_server.request_dataBreakpointInfo(
-            arr["variablesReference"], "[2]"
-        )
-
-        # Test response from dataBreakpointInfo request.
-        self.assertEquals(response_x["body"]["dataId"].split("/")[1], "4")
-        self.assertEquals(response_x["body"]["accessTypes"], self.accessTypes)
-        self.assertEquals(response_arr_2["body"]["dataId"].split("/")[1], "1")
-        self.assertEquals(response_arr_2["body"]["accessTypes"], self.accessTypes)
-        dataBreakpoints = [
-            {"dataId": response_x["body"]["dataId"], "accessType": "write"},
-            {"dataId": response_arr_2["body"]["dataId"], "accessType": "write"},
-        ]
-        self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-
-        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.assertEquals(x_val, "2")
-        self.assertEquals(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.assertEquals(arr_2["value"], "'z'")
-        self.assertEquals(i_val, "2")
-        self.dap_server.request_setDataBreakpoint([])
-
-        # Test hit condition
-        second_loop_break_line = line_number(source, "// second loop breakpoint")
-        breakpoint_ids = self.set_source_breakpoints(source, [second_loop_break_line])
-        self.continue_to_breakpoints(breakpoint_ids)
-        dataBreakpoints = [
-            {
-                "dataId": response_x["body"]["dataId"],
-                "accessType": "write",
-                "hitCondition": "2",
-            }
-        ]
-        self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.continue_to_next_stop()
-        x_val = self.dap_server.get_local_variable_value("x")
-        self.assertEquals(x_val, "3")
-
-        # Test condition
-        dataBreakpoints = [
-            {
-                "dataId": response_x["body"]["dataId"],
-                "accessType": "write",
-                "condition": "x==10",
-            }
-        ]
-        self.dap_server.request_setDataBreakpoint(dataBreakpoints)
-        self.continue_to_next_stop()
-        x_val = self.dap_server.get_local_variable_value("x")
-        self.assertEquals(x_val, "10")
diff --git a/lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp b/lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp
deleted file mode 100644
index 8082fe02f3e534..00000000000000
--- a/lldb/test/API/tools/lldb-dap/databreakpoint/main.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-int main(int argc, char const *argv[]) {
-  // Test for data breakpoint
-  int x = 0;
-  char arr[4] = {'a', 'b', 'c', 'd'};
-  for (int i = 0; i < 5; ++i) { // first loop breakpoint
-    if (i == 1) {
-      x = i + 1;
-    } else if (i == 2) {
-      arr[i] = 'z';
-    }
-  }
-
-  x = 1;
-  for (int i = 0; i < 10; ++i) { // second loop breakpoint
-    ++x;
-  }
-}
diff --git a/lldb/tools/lldb-dap/CMakeLists.txt b/lldb/tools/lldb-dap/CMakeLists.txt
index f8f0d86453f585..f8c0e4ecf36c2f 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -37,7 +37,6 @@ add_lldb_tool(lldb-dap
   RunInTerminal.cpp
   SourceBreakpoint.cpp
   DAP.cpp
-  Watchpoint.cpp
 
   LINK_LIBS
     liblldb
diff --git a/lldb/tools/lldb-dap/DAPForward.h b/lldb/tools/lldb-dap/DAPForward.h
index 8c79488fae8dbf..fffff1e3f79020 100644
--- a/lldb/tools/lldb-dap/DAPForward.h
+++ b/lldb/tools/lldb-dap/DAPForward.h
@@ -14,7 +14,6 @@ struct BreakpointBase;
 struct ExceptionBreakpoint;
 struct FunctionBreakpoint;
 struct SourceBreakpoint;
-struct Watchpoint;
 } // namespace lldb_dap
 
 namespace lldb {
@@ -40,7 +39,6 @@ class SBStringList;
 class SBTarget;
 class SBThread;
 class SBValue;
-class SBWatchpoint;
 } // namespace lldb
 
 #endif
diff --git a/lldb/tools/lldb-dap/Watchpoint.cpp b/lldb/tools/lldb-dap/Watchpoint.cpp
deleted file mode 100644
index 2f176e0da84f15..00000000000000
--- a/lldb/tools/lldb-dap/Watchpoint.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===-- Watchpoint.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 "Watchpoint.h"
-#include "DAP.h"
-#include "JSONUtils.h"
-#include "llvm/ADT/StringExtras.h"
-
-namespace lldb_dap {
-Watchpoint::Watchpoint(const llvm::json::Object &obj) : BreakpointBase(obj) {
-  llvm::StringRef dataId = GetString(obj, "dataId");
-  std::string accessType = GetString(obj, "accessType").str();
-  auto [addr_str, size_str] = dataId.split('/');
-  lldb::addr_t addr;
-  size_t size;
-  llvm::to_integer(addr_str, addr, 16);
-  llvm::to_integer(size_str, size);
-  lldb::SBWatchpointOptions options;
-  options.SetWatchpointTypeRead(accessType != "write");
-  if (accessType != "read")
-    options.SetWatchpointTypeWrite(lldb::eWatchpointWriteTypeOnModify);
-  wp = g_dap.target.WatchpointCreateByAddress(addr, size, options, error);
-  SetCondition();
-  SetHitCondition();
-}
-
-void Watchpoint::SetCondition() { wp.SetCondition(condition.c_str()); }
-
-void Watchpoint::SetHitCondition() {
-  uint64_t hitCount = 0;
-  if (llvm::to_integer(hitCondition, hitCount))
-    wp.SetIgnoreCount(hitCount - 1);
-}
-
-void Watchpoint::CreateJsonObject(llvm::json::Object &object) {
-  if (error.Success()) {
-    object.try_emplace("verified", true);
-  } else {
-    object.try_emplace("verified", false);
-    EmplaceSafeString(object, "message", error.GetCString());
-  }
-}
-} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Watchpoint.h b/lldb/tools/lldb-dap/Watchpoint.h
deleted file mode 100644
index 026b07d67241ce..00000000000000
--- a/lldb/tools/lldb-dap/Watchpoint.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===-- Watchpoint.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_WATCHPOINT_H
-#define LLDB_TOOLS_LLDB_DAP_WATCHPOINT_H
-
-#include "BreakpointBase.h"
-#include "lldb/API/SBError.h"
-#include "lldb/API/SBWatchpoint.h"
-#include "lldb/API/SBWatchpointOptions.h"
-
-namespace lldb_dap {
-
-struct Watchpoint : public BreakpointBase {
-  // The LLDB breakpoint associated wit this watchpoint.
-  lldb::SBWatchpoint wp;
-  lldb::SBError error;
-
-  Watchpoint() = default;
-  Watchpoint(const llvm::json::Object &obj);
-  Watchpoint(lldb::SBWatchpoint wp) : wp(wp) {}
-
-  void SetCondition() override;
-  void SetHitCondition() override;
-  void CreateJsonObject(llvm::json::Object &object) override;
-};
-} // namespace lldb_dap
-
-#endif
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 6bf2ec28432cd3..67022347e6d624 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "DAP.h"
-#include "Watchpoint.h"
 
 #include <cassert>
 #include <climits>
@@ -561,46 +560,6 @@ void EventThreadFunction() {
   }
 }
 
-lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef name) {
-  lldb::SBValue variable;
-  if (lldb::SBValueList *top_scope = GetTopLevelScope(variablesReference)) {
-    bool is_duplicated_variable_name = name.contains(" @");
-    // variablesReference is one of our scopes, not an actual variable it is
-    // asking for a variable in locals or globals or registers
-    int64_t end_idx = top_scope->GetSize();
-    // Searching backward so that we choose the variable in closest scope
-    // among variables of the same name.
-    for (int64_t i = end_idx - 1; i >= 0; --i) {
-      lldb::SBValue curr_variable = top_scope->GetValueAtIndex(i);
-      std::string variable_name = CreateUniqueVariableNameForDisplay(
-          curr_variable, is_duplicated_variable_name);
-      if (variable_name == name) {
-        variable = curr_variable;
-        break;
-      }
-    }
-  } else {
-    // This is not under the globals or locals scope, so there are no duplicated
-    // names.
-
-    // We have a named item within an actual variable so we need to find it
-    // withing the container variable by name.
-    lldb::SBValue container = g_dap.variables.GetVariable(variablesReference);
-    variable = container.GetChildMemberWithName(name.data());
-    if (!variable.IsValid()) {
-      if (name.starts_with("[")) {
-        llvm::StringRef index_str(name.drop_front(1));
-        uint64_t index = 0;
-        if (!index_str.consumeInteger(0, index)) {
-          if (index_str == "]")
-            variable = container.GetChildAtIndex(index);
-        }
-      }
-    }
-  }
-  return variable;
-}
-
 // Both attach and launch take a either a sourcePath or sourceMap
 // argument (or neither), from which we need to set the target.source-map.
 void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
@@ -1688,8 +1647,6 @@ void request_initialize(const llvm::json::Object &request) {
   body.try_emplace("supportsProgressReporting", true);
   // The debug adapter supports 'logMessage' in breakpoint.
   body.try_emplace("supportsLogPoints", true);
-  // The debug adapter supports data watchpoints.
-  body.try_emplace("supportsDataBreakpoints", true);
 
   response.try_emplace("body", std::move(body));
   g_dap.SendJSON(llvm::json::Value(std::move(response)));
@@ -2634,231 +2591,6 @@ void request_setFunctionBreakpoints(const llvm::json::Object &request) {
   g_dap.SendJSON(llvm::json::Value(std::move(response)));
 }
 
-// "DataBreakpointInfoRequest": {
-//   "allOf": [ { "$ref": "#/definitions/Request" }, {
-//     "type": "object",
-//     "description": "Obtains information on a possible data breakpoint that
-//     could be set on an expression or variable.\nClients should only call this
-//     request if the corresponding capability `supportsDataBreakpoints` is
-//     true.", "properties": {
-//       "command": {
-//         "type": "string",
-//         "enum": [ "dataBreakpointInfo" ]
-//       },
-//       "arguments": {
-//         "$ref": "#/definitions/DataBreakpointInfoArguments"
-//       }
-//     },
-//     "required": [ "command", "arguments"  ]
-//   }]
-// },
-// "DataBreakpointInfoArguments": {
-//   "type": "object",
-//   "description": "Arguments for `dataBreakpointInfo` request.",
-//   "properties": {
-//     "variablesReference": {
-//       "type": "integer",
-//       "description": "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."
-//     },
-//     "name": {
-//       "type": "string",
-//       "description": "The name of the variable's child to obtain data
-//       breakpoint information for.\nIf `variablesReference` isn't specified,
-//       this can be an expression."
-//     },
-//     "frameId": {
-//       "type": "integer",
-//       "description": "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 `variablesReference` is specified, this property
-//       has no effect."
-//     }
-//   },
-//   "required": [ "name" ]
-// },
-// "DataBreakpointInfoResponse": {
-//   "allOf": [ { "$ref": "#/definitions/Response" }, {
-//     "type": "object",
-//     "description": "Response to `dataBreakpointInfo` request.",
-//     "properties": {
-//       "body": {
-//         "type": "object",
-//         "properties": {
-//           "dataId": {
-//             "type": [ "string", "null" ],
-//             "description": "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`."
-//           },
-//           "description": {
-//             "type": "string",
-//             "description": "UI string that describes on what data the
-//             breakpoint is set on or why a data breakpoint is not available."
-//           },
-//           "accessTypes": {
-//             "type": "array",
-//             "items": {
-//               "$ref": "#/definitions/DataBreakpointAccessType"
-//             },
-//             "description": "Attribute lists the available access types for a
-//             potential data breakpoint. A UI client could surface this
-//             information."
-//           },
-//           "canPersist": {
-//             "type": "boolean",
-//             "description": "Attribute indicates that a potential data
-//             breakpoint could be persisted across sessions."
-//           }
-//         },
-//         "required": [ "dataId", "description" ]
-//       }
-//     },
-//     "required": [ "body" ]
-//   }]
-// }
-void request_dataBreakpointInfo(const llvm::json::Object &request) {
-  llvm::json::Object response;
-  FillResponse(request, response);
-  llvm::json::Object body;
-  lldb::SBError error;
-  llvm::json::Array accessTypes{"read", "write", "readWrite"};
-  const auto *arguments = request.getObject("arguments");
-  const auto variablesReference =
-      GetUnsigned(arguments, "variablesReference", 0);
-  llvm::StringRef name = GetString(arguments, "name");
-  lldb::SBFrame frame = g_dap.GetLLDBFrame(*arguments);
-  lldb::SBValue variable = FindVariable(variablesReference, name);
-  std::string addr, size;
-
-  if (variable.IsValid()) {
-    addr = llvm::utohexstr(variable.GetLoadAddress());
-    size = llvm::utostr(variable.GetByteSize());
-  } else if (variablesReference == 0 && frame.IsValid()) {
-    // Name might be an expression. In this case we assume that name is composed
-    // of the number of bytes to watch and expression, separated by '@':
-    // "${size}@${expression}"
-    llvm::StringRef expr;
-    std::tie(size, expr) = name.split('@');
-    lldb::SBValue value = frame.EvaluateExpression(expr.data());
-    if (value.GetError().Fail()) {
-      lldb::SBError error = value.GetError();
-      const char *error_cstr = error.GetCString();
-      body.try_emplace("dataId", nullptr);
-      body.try_emplace("description", error_cstr && error_cstr[0]
-                                          ? std::string(error_cstr)
-                                          : "evaluation failed");
-    } else
-      addr = llvm::utohexstr(value.GetValueAsUnsigned());
-  } else {
-    auto state = g_dap.target.GetProcess().GetState();
-    body.try_emplace("dataId", nullptr);
-    body.try_emplace("description",
-                     "variable not found: " + llvm::utostr(state));
-  }
-
-  if (!body.getObject("dataId")) {
-    body.try_emplace("dataId", addr + "/" + size);
-    body.try_emplace("accessTypes", std::move(accessTypes));
-    body.try_emplace("description",
-                     size + " bytes at " + addr + " " + name.str());
-  }
-  response.try_emplace("body", std::move(body));
-  g_dap.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-// "SetDataBreakpointsRequest": {
-//   "allOf": [ { "$ref": "#/definitions/Request" }, {
-//     "type": "object",
-//     "description": "Replaces all existing data breakpoints with new data
-//     breakpoints.\nTo clear all data breakpoints, specify an empty
-//     array.\nWhen a data breakpoint is hit, a `stopped` event (with reason
-//     `data breakpoint`) is generated.\nClients should only call this request
-//     if the corresponding capability `supportsDataBreakpoints` is true.",
-//     "properties": {
-//       "command": {
-//         "type": "string",
-//         "enum": [ "setDataBreakpoints" ]
-//       },
-//       "arguments": {
-//         "$ref": "#/definitions/SetDataBreakpointsArguments"
-//       }
-//     },
-//     "required": [ "command", "arguments"  ]
-//   }]
-// },
-// "SetDataBreakpointsArguments": {
-//   "type": "object",
-//   "description": "Arguments for `setDataBreakpoints` request.",
-//   "properties": {
-//     "breakpoints": {
-//       "type": "array",
-//       "items": {
-//         "$ref": "#/definitions/DataBreakpoint"
-//       },
-//       "description": "The contents of this array replaces all existing data
-//       breakpoints. An empty array clears all data breakpoints."
-//     }
-//   },
-//   "required": [ "breakpoints" ]
-// },
-// "SetDataBreakpointsResponse": {
-//   "allOf": [ { "$ref": "#/definitions/Response" }, {
-//     "type": "object",
-//     "description": "Response to `setDataBreakpoints` request.\nReturned is
-//     information about each breakpoint created by this request.",
-//     "properties": {
-//       "body": {
-//         "type": "object",
-//         "properties": {
-//           "breakpoints": {
-//             "type": "array",
-//             "items": {
-//               "$ref": "#/definitions/Breakpoint"
-//             },
-//             "description": "Information about the data breakpoints. The array
-//             elements correspond to the elements of the input argument
-//             `breakpoints` array."
-//           }
-//         },
-//         "required": [ "breakpoints" ]
-//       }
-//     },
-//     "required": [ "body" ]
-//   }]
-// }
-void request_setDataBreakpoints(const llvm::json::Object &request) {
-  llvm::json::Object response;
-  lldb::SBError error;
-  FillResponse(request, response);
-  const auto *arguments = request.getObject("arguments");
-  const auto *breakpoints = arguments->getArray("breakpoints");
-  llvm::json::Array response_breakpoints;
-  g_dap.target.DeleteAllWatchpoints();
-  if (breakpoints) {
-    for (const auto &bp : *breakpoints) {
-      const auto *bp_obj = bp.getAsObject();
-      if (bp_obj) {
-        Watchpoint wp(*bp_obj);
-        AppendBreakpoint(&wp, response_breakpoints);
-      }
-    }
-  }
-  llvm::json::Object body;
-  body.try_emplace("breakpoints", std::move(response_breakpoints));
-  response.try_emplace("body", std::move(body));
-  g_dap.SendJSON(llvm::json::Value(std::move(response)));
-}
-
 // "SourceRequest": {
 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
 //     "type": "object",
@@ -3342,6 +3074,7 @@ void request_setVariable(const llvm::json::Object &request) {
   const auto variablesReference =
       GetUnsigned(arguments, "variablesReference", 0);
   llvm::StringRef name = GetString(arguments, "name");
+  bool is_duplicated_variable_name = name.contains(" @");
 
   const auto value = GetString(arguments, "value");
   // Set success to false just in case we don't find the variable by name
@@ -3362,8 +3095,40 @@ void request_setVariable(const llvm::json::Object &request) {
   const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
   if (id_value != UINT64_MAX) {
     variable = g_dap.variables.GetVariable(id_value);
+  } else if (lldb::SBValueList *top_scope =
+                 GetTopLevelScope(variablesReference)) {
+    // variablesReference is one of our scopes, not an actual variable it is
+    // asking for a variable in locals or globals or registers
+    int64_t end_idx = top_scope->GetSize();
+    // Searching backward so that we choose the variable in closest scope
+    // among variables of the same name.
+    for (int64_t i = end_idx - 1; i >= 0; --i) {
+      lldb::SBValue curr_variable = top_scope->GetValueAtIndex(i);
+      std::string variable_name = CreateUniqueVariableNameForDisplay(
+          curr_variable, is_duplicated_variable_name);
+      if (variable_name == name) {
+        variable = curr_variable;
+        break;
+      }
+    }
   } else {
-    variable = FindVariable(variablesReference, name);
+    // This is not under the globals or locals scope, so there are no duplicated
+    // names.
+
+    // We have a named item within an actual variable so we need to find it
+    // withing the container variable by name.
+    lldb::SBValue container = g_dap.variables.GetVariable(variablesReference);
+    variable = container.GetChildMemberWithName(name.data());
+    if (!variable.IsValid()) {
+      if (name.starts_with("[")) {
+        llvm::StringRef index_str(name.drop_front(1));
+        uint64_t index = 0;
+        if (!index_str.consumeInteger(0, index)) {
+          if (index_str == "]")
+            variable = container.GetChildAtIndex(index);
+        }
+      }
+    }
   }
 
   if (variable.IsValid()) {
@@ -3846,10 +3611,6 @@ void RegisterRequestCallbacks() {
                                 request_setExceptionBreakpoints);
   g_dap.RegisterRequestCallback("setFunctionBreakpoints",
                                 request_setFunctionBreakpoints);
-  g_dap.RegisterRequestCallback("dataBreakpointInfo",
-                                request_dataBreakpointInfo);
-  g_dap.RegisterRequestCallback("setDataBreakpoints",
-                                request_setDataBreakpoints);
   g_dap.RegisterRequestCallback("setVariable", request_setVariable);
   g_dap.RegisterRequestCallback("source", request_source);
   g_dap.RegisterRequestCallback("stackTrace", request_stackTrace);
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 a752b61bdbaabf..98c2068f6da291 100644
--- a/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn
+++ b/llvm/utils/gn/secondary/lldb/tools/lldb-dap/BUILD.gn
@@ -52,6 +52,5 @@ executable("lldb-dap") {
     "RunInTerminal.cpp",
     "SourceBreakpoint.cpp",
     "lldb-dap.cpp",
-    "Watchpoint.cpp",
   ]
 }



More information about the llvm-commits mailing list