From 6c74a6f6f4f01500f9deabadc7673b4935643928 Mon Sep 17 00:00:00 2001 From: Prabhuk Date: Wed, 14 Feb 2024 22:07:26 -0800 Subject: Revert "[lldb-dap] Add support for data breakpoint. (#81541)" (#81812) This reverts commit 8c56e78ec531f0e2460213c20fff869b6b7add99. Reverting to address the LLDB test failure in ARM64. --- .../lldbsuite/test/tools/lldb-dap/dap_server.py | 47 ---- .../API/tools/lldb-dap/databreakpoint/Makefile | 3 - .../databreakpoint/TestDAP_setDataBreakpoints.py | 123 --------- .../API/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 27a76a6..bb863bb 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 @@ class DebugCommunication(object): 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 @@ class DebugCommunication(object): } 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 99998b2..0000000 --- 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 40ca647..0000000 --- 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@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 8082fe0..0000000 --- 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 f8f0d86..f8c0e4e 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 8c79488..fffff1e 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 2f176e0..0000000 --- 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 026b07d..0000000 --- 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 6bf2ec2..6702234 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 #include @@ -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 a752b61b..98c2068 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", ] } -- cgit v1.1