https://github.com/JDevlieghere updated 
https://github.com/llvm/llvm-project/pull/128550

>From 95f575e5f58a4d4285377f9f6d0807573da90e44 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jo...@devlieghere.com>
Date: Mon, 24 Feb 2025 11:51:28 -0600
Subject: [PATCH 1/3] [lldb-dap] Refactor breakpoint related request handlers
 (NFC)

---
 lldb/tools/lldb-dap/CMakeLists.txt            |   7 +-
 .../DataBreakpointInfoRequestHandler.cpp      | 190 ++++
 .../tools/lldb-dap/Handler/RequestHandler.cpp |  55 ++
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |  47 +
 .../Handler/SetBreakpointsRequestHandler.cpp  | 182 ++++
 .../SetDataBreakpointsRequestHandler.cpp      | 114 +++
 .../SetExceptionBreakpointsRequestHandler.cpp |  93 ++
 .../SetFunctionBreakpointsRequestHandler.cpp  | 139 +++
 ...etInstructionBreakpointsRequestHandler.cpp | 249 +++++
 lldb/tools/lldb-dap/lldb-dap.cpp              | 880 +-----------------
 10 files changed, 1081 insertions(+), 875 deletions(-)
 create mode 100644 
lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
 create mode 100644 lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
 create mode 100644 
lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp
 create mode 100644 
lldb/tools/lldb-dap/Handler/SetExceptionBreakpointsRequestHandler.cpp
 create mode 100644 
lldb/tools/lldb-dap/Handler/SetFunctionBreakpointsRequestHandler.cpp
 create mode 100644 
lldb/tools/lldb-dap/Handler/SetInstructionBreakpointsRequestHandler.cpp

diff --git a/lldb/tools/lldb-dap/CMakeLists.txt 
b/lldb/tools/lldb-dap/CMakeLists.txt
index 688a2e448f71d..c04b10861a4c5 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -43,6 +43,7 @@ add_lldb_tool(lldb-dap
   Handler/CompletionsHandler.cpp
   Handler/ConfigurationDoneRequestHandler.cpp
   Handler/ContinueRequestHandler.cpp
+  Handler/DataBreakpointInfoRequestHandler.cpp
   Handler/DisconnectRequestHandler.cpp
   Handler/EvaluateRequestHandler.cpp
   Handler/ExceptionInfoRequestHandler.cpp
@@ -52,10 +53,14 @@ add_lldb_tool(lldb-dap
   Handler/NextRequestHandler.cpp
   Handler/RequestHandler.cpp
   Handler/RestartRequestHandler.cpp
+  Handler/SetBreakpointsRequestHandler.cpp
+  Handler/SetDataBreakpointsRequestHandler.cpp
+  Handler/SetExceptionBreakpointsRequestHandler.cpp
+  Handler/SetFunctionBreakpointsRequestHandler.cpp
+  Handler/SetInstructionBreakpointsRequestHandler.cpp 
Handler/StepOutRequestHandler.cpp
   Handler/StepInRequestHandler.cpp
   Handler/StepInTargetsRequestHandler.cpp
   Handler/TestGetTargetBreakpointsRequestHandler.cpp
-  Handler/StepOutRequestHandler.cpp
 
   LINK_LIBS
     liblldb
diff --git a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
new file mode 100644
index 0000000000000..519a9c728e4b3
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
@@ -0,0 +1,190 @@
+//===-- DataBreakpointInfoRequestHandler.cpp 
------------------------------===//
+//
+// 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 "DAP.h"
+#include "EventHelper.h"
+#include "JSONUtils.h"
+#include "RequestHandler.h"
+#include "lldb/API/SBMemoryRegionInfo.h"
+#include "llvm/ADT/StringExtras.h"
+
+namespace lldb_dap {
+
+// "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 DataBreakpointInfoRequestHandler::operator()(
+    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 = dap.GetLLDBFrame(*arguments);
+  lldb::SBValue variable = FindVariable(variablesReference, name);
+  std::string addr, size;
+
+  if (variable.IsValid()) {
+    lldb::addr_t load_addr = variable.GetLoadAddress();
+    size_t byte_size = variable.GetByteSize();
+    if (load_addr == LLDB_INVALID_ADDRESS) {
+      body.try_emplace("dataId", nullptr);
+      body.try_emplace("description",
+                       "does not exist in memory, its location is " +
+                           std::string(variable.GetLocation()));
+    } else if (byte_size == 0) {
+      body.try_emplace("dataId", nullptr);
+      body.try_emplace("description", "variable size is 0");
+    } else {
+      addr = llvm::utohexstr(load_addr);
+      size = llvm::utostr(byte_size);
+    }
+  } else if (variablesReference == 0 && frame.IsValid()) {
+    lldb::SBValue value = frame.EvaluateExpression(name.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 {
+      uint64_t load_addr = value.GetValueAsUnsigned();
+      lldb::SBData data = value.GetPointeeData();
+      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())) {
+            body.try_emplace("dataId", nullptr);
+            body.try_emplace("description",
+                             "memory region for address " + addr +
+                                 " has no read or write permissions");
+          }
+        }
+      } else {
+        body.try_emplace("dataId", nullptr);
+        body.try_emplace("description",
+                         "unable to get byte size for expression: " +
+                             name.str());
+      }
+    }
+  } else {
+    body.try_emplace("dataId", nullptr);
+    body.try_emplace("description", "variable not found: " + name.str());
+  }
+
+  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));
+  dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index f9502e09846d4..de313eb02a24a 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -232,4 +232,59 @@ bool RequestHandler::HasInstructionGranularity(
   return false;
 }
 
+lldb::SBValueList *
+RequestHandler::GetTopLevelScope(int64_t variablesReference) {
+  switch (variablesReference) {
+  case VARREF_LOCALS:
+    return &dap.variables.locals;
+  case VARREF_GLOBALS:
+    return &dap.variables.globals;
+  case VARREF_REGS:
+    return &dap.variables.registers;
+  default:
+    return nullptr;
+  }
+}
+
+lldb::SBValue RequestHandler::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 = 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;
+}
+
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h 
b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index 874b600181f43..a30e0dcc2bd04 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -52,6 +52,9 @@ class RequestHandler {
   // Check if the step-granularity is `instruction`.
   bool HasInstructionGranularity(const llvm::json::Object &request);
 
+  lldb::SBValueList *GetTopLevelScope(int64_t variablesReference);
+  lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef 
name);
+
   /// @}
 
   DAP &dap;
@@ -162,6 +165,50 @@ class StepOutRequestHandler : public RequestHandler {
   void operator()(const llvm::json::Object &request) override;
 };
 
+class SetBreakpointsRequestHandler : public RequestHandler {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral getCommand() { return "setBreakpoints"; }
+  void operator()(const llvm::json::Object &request) override;
+};
+
+class SetExceptionBreakpointsRequestHandler : public RequestHandler {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral getCommand() { return "setExceptionBreakpoints"; }
+  void operator()(const llvm::json::Object &request) override;
+};
+
+class SetFunctionBreakpointsRequestHandler : public RequestHandler {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral getCommand() { return "setFunctionBreakpoints"; }
+  void operator()(const llvm::json::Object &request) override;
+};
+
+class DataBreakpointInfoRequestHandler : public RequestHandler {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral getCommand() { return "dataBreakpointInfo"; }
+  void operator()(const llvm::json::Object &request) override;
+};
+
+class SetDataBreakpointsRequestHandler : public RequestHandler {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral getCommand() { return "setDataBreakpoints"; }
+  void operator()(const llvm::json::Object &request) override;
+};
+
+class SetInstructionBreakpointsRequestHandler : public RequestHandler {
+public:
+  using RequestHandler::RequestHandler;
+  static llvm::StringLiteral getCommand() {
+    return "setInstructionBreakpoints";
+  }
+  void operator()(const llvm::json::Object &request) override;
+};
+
 class CompileUnitsRequestHandler : public RequestHandler {
 public:
   using RequestHandler::RequestHandler;
diff --git a/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
new file mode 100644
index 0000000000000..6dbd24c130db6
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/SetBreakpointsRequestHandler.cpp
@@ -0,0 +1,182 @@
+//===-- SetBreakpointsRequestHandler.cpp 
----------------------------------===//
+//
+// 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 "DAP.h"
+#include "EventHelper.h"
+#include "JSONUtils.h"
+#include "RequestHandler.h"
+
+namespace lldb_dap {
+
+// "SetBreakpointsRequest": {
+//   "allOf": [ { "$ref": "#/definitions/Request" }, {
+//     "type": "object",
+//     "description": "SetBreakpoints request; value of command field is
+//     'setBreakpoints'. Sets multiple breakpoints for a single source and
+//     clears all previous breakpoints in that source. To clear all breakpoint
+//     for a source, specify an empty array. When a breakpoint is hit, a
+//     StoppedEvent (event type 'breakpoint') is generated.", "properties": {
+//       "command": {
+//         "type": "string",
+//         "enum": [ "setBreakpoints" ]
+//       },
+//       "arguments": {
+//         "$ref": "#/definitions/SetBreakpointsArguments"
+//       }
+//     },
+//     "required": [ "command", "arguments"  ]
+//   }]
+// },
+// "SetBreakpointsArguments": {
+//   "type": "object",
+//   "description": "Arguments for 'setBreakpoints' request.",
+//   "properties": {
+//     "source": {
+//       "$ref": "#/definitions/Source",
+//       "description": "The source location of the breakpoints; either
+//       source.path or source.reference must be specified."
+//     },
+//     "breakpoints": {
+//       "type": "array",
+//       "items": {
+//         "$ref": "#/definitions/SourceBreakpoint"
+//       },
+//       "description": "The code locations of the breakpoints."
+//     },
+//     "lines": {
+//       "type": "array",
+//       "items": {
+//         "type": "integer"
+//       },
+//       "description": "Deprecated: The code locations of the breakpoints."
+//     },
+//     "sourceModified": {
+//       "type": "boolean",
+//       "description": "A value of true indicates that the underlying source
+//       has been modified which results in new breakpoint locations."
+//     }
+//   },
+//   "required": [ "source" ]
+// },
+// "SetBreakpointsResponse": {
+//   "allOf": [ { "$ref": "#/definitions/Response" }, {
+//     "type": "object",
+//     "description": "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') in the
+//     SetBreakpointsArguments.", "properties": {
+//       "body": {
+//         "type": "object",
+//         "properties": {
+//           "breakpoints": {
+//             "type": "array",
+//             "items": {
+//               "$ref": "#/definitions/Breakpoint"
+//             },
+//             "description": "Information about the breakpoints. The array
+//             elements are in the same order as the elements of the
+//             'breakpoints' (or the deprecated 'lines') in the
+//             SetBreakpointsArguments."
+//           }
+//         },
+//         "required": [ "breakpoints" ]
+//       }
+//     },
+//     "required": [ "body" ]
+//   }]
+// },
+// "SourceBreakpoint": {
+//   "type": "object",
+//   "description": "Properties of a breakpoint or logpoint passed to the
+//   setBreakpoints request.", "properties": {
+//     "line": {
+//       "type": "integer",
+//       "description": "The source line of the breakpoint or logpoint."
+//     },
+//     "column": {
+//       "type": "integer",
+//       "description": "An optional source column of the breakpoint."
+//     },
+//     "condition": {
+//       "type": "string",
+//       "description": "An optional expression for conditional breakpoints."
+//     },
+//     "hitCondition": {
+//       "type": "string",
+//       "description": "An optional expression that controls how many hits of
+//       the breakpoint are ignored. The backend is expected to interpret the
+//       expression as needed."
+//     },
+//     "logMessage": {
+//       "type": "string",
+//       "description": "If this attribute exists and is non-empty, the backend
+//       must not 'break' (stop) but log the message instead. Expressions 
within
+//       {} are interpolated."
+//     }
+//   },
+//   "required": [ "line" ]
+// }
+void SetBreakpointsRequestHandler::operator()(
+    const llvm::json::Object &request) {
+  llvm::json::Object response;
+  lldb::SBError error;
+  FillResponse(request, response);
+  const auto *arguments = request.getObject("arguments");
+  const auto *source = arguments->getObject("source");
+  const auto path = GetString(source, "path");
+  const auto *breakpoints = arguments->getArray("breakpoints");
+  llvm::json::Array response_breakpoints;
+
+  // Decode the source breakpoint infos for this "setBreakpoints" request
+  SourceBreakpointMap request_bps;
+  // "breakpoints" may be unset, in which case we treat it the same as being 
set
+  // to an empty array.
+  if (breakpoints) {
+    for (const auto &bp : *breakpoints) {
+      const auto *bp_obj = bp.getAsObject();
+      if (bp_obj) {
+        SourceBreakpoint src_bp(dap, *bp_obj);
+        std::pair<uint32_t, uint32_t> bp_pos(src_bp.line, src_bp.column);
+        request_bps.try_emplace(bp_pos, src_bp);
+        const auto [iv, inserted] =
+            dap.source_breakpoints[path].try_emplace(bp_pos, src_bp);
+        // We check if this breakpoint already exists to update it
+        if (inserted)
+          iv->getSecond().SetBreakpoint(path.data());
+        else
+          iv->getSecond().UpdateBreakpoint(src_bp);
+        AppendBreakpoint(&iv->getSecond(), response_breakpoints, path,
+                         src_bp.line);
+      }
+    }
+  }
+
+  // Delete any breakpoints in this source file that aren't in the
+  // request_bps set. There is no call to remove breakpoints other than
+  // calling this function with a smaller or empty "breakpoints" list.
+  auto old_src_bp_pos = dap.source_breakpoints.find(path);
+  if (old_src_bp_pos != dap.source_breakpoints.end()) {
+    for (auto &old_bp : old_src_bp_pos->second) {
+      auto request_pos = request_bps.find(old_bp.first);
+      if (request_pos == request_bps.end()) {
+        // This breakpoint no longer exists in this source file, delete it
+        dap.target.BreakpointDelete(old_bp.second.bp.GetID());
+        old_src_bp_pos->second.erase(old_bp.first);
+      }
+    }
+  }
+
+  llvm::json::Object body;
+  body.try_emplace("breakpoints", std::move(response_breakpoints));
+  response.try_emplace("body", std::move(body));
+  dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp
new file mode 100644
index 0000000000000..9c2308f7a6bcd
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/SetDataBreakpointsRequestHandler.cpp
@@ -0,0 +1,114 @@
+//===-- SetDataBreakpointsRequestHandler.cpp 
------------------------------===//
+//
+// 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 "DAP.h"
+#include "EventHelper.h"
+#include "JSONUtils.h"
+#include "RequestHandler.h"
+#include "Watchpoint.h"
+#include <set>
+
+namespace lldb_dap {
+
+// "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 SetDataBreakpointsRequestHandler::operator()(
+    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;
+  dap.target.DeleteAllWatchpoints();
+  std::vector<Watchpoint> watchpoints;
+  if (breakpoints) {
+    for (const auto &bp : *breakpoints) {
+      const auto *bp_obj = bp.getAsObject();
+      if (bp_obj)
+        watchpoints.emplace_back(dap, *bp_obj);
+    }
+  }
+  // If two watchpoints start at the same address, the latter overwrite the
+  // former. So, we only enable those at first-seen addresses when iterating
+  // backward.
+  std::set<lldb::addr_t> addresses;
+  for (auto iter = watchpoints.rbegin(); iter != watchpoints.rend(); ++iter) {
+    if (addresses.count(iter->addr) == 0) {
+      iter->SetWatchpoint();
+      addresses.insert(iter->addr);
+    }
+  }
+  for (auto wp : watchpoints)
+    AppendBreakpoint(&wp, response_breakpoints);
+
+  llvm::json::Object body;
+  body.try_emplace("breakpoints", std::move(response_breakpoints));
+  response.try_emplace("body", std::move(body));
+  dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+} // namespace lldb_dap
diff --git 
a/lldb/tools/lldb-dap/Handler/SetExceptionBreakpointsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/SetExceptionBreakpointsRequestHandler.cpp
new file mode 100644
index 0000000000000..d208525385094
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/SetExceptionBreakpointsRequestHandler.cpp
@@ -0,0 +1,93 @@
+//===-- SetExceptionBreakpointsRequestHandler.cpp 
-------------------------===//
+//
+// 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 "DAP.h"
+#include "EventHelper.h"
+#include "JSONUtils.h"
+#include "RequestHandler.h"
+#include <set>
+
+namespace lldb_dap {
+
+// "SetExceptionBreakpointsRequest": {
+//   "allOf": [ { "$ref": "#/definitions/Request" }, {
+//     "type": "object",
+//     "description": "SetExceptionBreakpoints request; value of command field
+//     is 'setExceptionBreakpoints'. The request configures the debuggers
+//     response to thrown exceptions. If an exception is configured to break, a
+//     StoppedEvent is fired (event type 'exception').", "properties": {
+//       "command": {
+//         "type": "string",
+//         "enum": [ "setExceptionBreakpoints" ]
+//       },
+//       "arguments": {
+//         "$ref": "#/definitions/SetExceptionBreakpointsArguments"
+//       }
+//     },
+//     "required": [ "command", "arguments"  ]
+//   }]
+// },
+// "SetExceptionBreakpointsArguments": {
+//   "type": "object",
+//   "description": "Arguments for 'setExceptionBreakpoints' request.",
+//   "properties": {
+//     "filters": {
+//       "type": "array",
+//       "items": {
+//         "type": "string"
+//       },
+//       "description": "IDs of checked exception options. The set of IDs is
+//       returned via the 'exceptionBreakpointFilters' capability."
+//     },
+//     "exceptionOptions": {
+//       "type": "array",
+//       "items": {
+//         "$ref": "#/definitions/ExceptionOptions"
+//       },
+//       "description": "Configuration options for selected exceptions."
+//     }
+//   },
+//   "required": [ "filters" ]
+// },
+// "SetExceptionBreakpointsResponse": {
+//   "allOf": [ { "$ref": "#/definitions/Response" }, {
+//     "type": "object",
+//     "description": "Response to 'setExceptionBreakpoints' request. This is
+//     just an acknowledgement, so no body field is required."
+//   }]
+// }
+void SetExceptionBreakpointsRequestHandler::operator()(
+    const llvm::json::Object &request) {
+  llvm::json::Object response;
+  lldb::SBError error;
+  FillResponse(request, response);
+  const auto *arguments = request.getObject("arguments");
+  const auto *filters = arguments->getArray("filters");
+  // Keep a list of any exception breakpoint filter names that weren't set
+  // so we can clear any exception breakpoints if needed.
+  std::set<std::string> unset_filters;
+  for (const auto &bp : *dap.exception_breakpoints)
+    unset_filters.insert(bp.filter);
+
+  for (const auto &value : *filters) {
+    const auto filter = GetAsString(value);
+    auto *exc_bp = dap.GetExceptionBreakpoint(std::string(filter));
+    if (exc_bp) {
+      exc_bp->SetBreakpoint();
+      unset_filters.erase(std::string(filter));
+    }
+  }
+  for (const auto &filter : unset_filters) {
+    auto *exc_bp = dap.GetExceptionBreakpoint(filter);
+    if (exc_bp)
+      exc_bp->ClearBreakpoint();
+  }
+  dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+} // namespace lldb_dap
diff --git 
a/lldb/tools/lldb-dap/Handler/SetFunctionBreakpointsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/SetFunctionBreakpointsRequestHandler.cpp
new file mode 100644
index 0000000000000..e55cfaef8c897
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/SetFunctionBreakpointsRequestHandler.cpp
@@ -0,0 +1,139 @@
+//===-- SetFunctionBreakpointsRequestHandler.cpp 
--------------------------===//
+//
+// 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 "DAP.h"
+#include "EventHelper.h"
+#include "JSONUtils.h"
+#include "RequestHandler.h"
+
+namespace lldb_dap {
+
+// "SetFunctionBreakpointsRequest": {
+//   "allOf": [ { "$ref": "#/definitions/Request" }, {
+//     "type": "object",
+//     "description": "SetFunctionBreakpoints request; value of command field 
is
+//     'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
+//     all previous function breakpoints. To clear all function breakpoint,
+//     specify an empty array. When a function breakpoint is hit, a 
StoppedEvent
+//     (event type 'function breakpoint') is generated.", "properties": {
+//       "command": {
+//         "type": "string",
+//         "enum": [ "setFunctionBreakpoints" ]
+//       },
+//       "arguments": {
+//         "$ref": "#/definitions/SetFunctionBreakpointsArguments"
+//       }
+//     },
+//     "required": [ "command", "arguments"  ]
+//   }]
+// },
+// "SetFunctionBreakpointsArguments": {
+//   "type": "object",
+//   "description": "Arguments for 'setFunctionBreakpoints' request.",
+//   "properties": {
+//     "breakpoints": {
+//       "type": "array",
+//       "items": {
+//         "$ref": "#/definitions/FunctionBreakpoint"
+//       },
+//       "description": "The function names of the breakpoints."
+//     }
+//   },
+//   "required": [ "breakpoints" ]
+// },
+// "FunctionBreakpoint": {
+//   "type": "object",
+//   "description": "Properties of a breakpoint passed to the
+//   setFunctionBreakpoints request.", "properties": {
+//     "name": {
+//       "type": "string",
+//       "description": "The name of the function."
+//     },
+//     "condition": {
+//       "type": "string",
+//       "description": "An optional expression for conditional breakpoints."
+//     },
+//     "hitCondition": {
+//       "type": "string",
+//       "description": "An optional expression that controls how many hits of
+//       the breakpoint are ignored. The backend is expected to interpret the
+//       expression as needed."
+//     }
+//   },
+//   "required": [ "name" ]
+// },
+// "SetFunctionBreakpointsResponse": {
+//   "allOf": [ { "$ref": "#/definitions/Response" }, {
+//     "type": "object",
+//     "description": "Response to 'setFunctionBreakpoints' request. Returned 
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 breakpoints. The array
+//             elements correspond to the elements of the 'breakpoints' array."
+//           }
+//         },
+//         "required": [ "breakpoints" ]
+//       }
+//     },
+//     "required": [ "body" ]
+//   }]
+// }
+void SetFunctionBreakpointsRequestHandler::operator()(
+    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;
+
+  // Disable any function breakpoints that aren't in this request.
+  // There is no call to remove function breakpoints other than calling this
+  // function with a smaller or empty "breakpoints" list.
+  const auto name_iter = dap.function_breakpoints.keys();
+  llvm::DenseSet<llvm::StringRef> seen(name_iter.begin(), name_iter.end());
+  for (const auto &value : *breakpoints) {
+    const auto *bp_obj = value.getAsObject();
+    if (!bp_obj)
+      continue;
+    FunctionBreakpoint fn_bp(dap, *bp_obj);
+    const auto [it, inserted] =
+        dap.function_breakpoints.try_emplace(fn_bp.functionName, dap, *bp_obj);
+    if (inserted)
+      it->second.SetBreakpoint();
+    else
+      it->second.UpdateBreakpoint(fn_bp);
+
+    AppendBreakpoint(&it->second, response_breakpoints);
+    seen.erase(fn_bp.functionName);
+  }
+
+  // Remove any breakpoints that are no longer in our list
+  for (const auto &name : seen) {
+    auto fn_bp = dap.function_breakpoints.find(name);
+    if (fn_bp == dap.function_breakpoints.end())
+      continue;
+    dap.target.BreakpointDelete(fn_bp->second.bp.GetID());
+    dap.function_breakpoints.erase(name);
+  }
+
+  llvm::json::Object body;
+  body.try_emplace("breakpoints", std::move(response_breakpoints));
+  response.try_emplace("body", std::move(body));
+  dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+} // namespace lldb_dap
diff --git 
a/lldb/tools/lldb-dap/Handler/SetInstructionBreakpointsRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/SetInstructionBreakpointsRequestHandler.cpp
new file mode 100644
index 0000000000000..636d9b814ab76
--- /dev/null
+++ b/lldb/tools/lldb-dap/Handler/SetInstructionBreakpointsRequestHandler.cpp
@@ -0,0 +1,249 @@
+//===-- SetInstructionBreakpointsRequestHandler.cpp 
-----------------------===//
+//
+// 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 "DAP.h"
+#include "EventHelper.h"
+#include "JSONUtils.h"
+#include "RequestHandler.h"
+
+namespace lldb_dap {
+
+// "SetInstructionBreakpointsRequest": {
+//   "allOf": [
+//     {"$ref": "#/definitions/Request"},
+//     {
+//       "type": "object",
+//       "description" :
+//           "Replaces all existing instruction breakpoints. Typically, "
+//           "instruction breakpoints would be set from a disassembly window. "
+//           "\nTo clear all instruction breakpoints, specify an empty "
+//           "array.\nWhen an instruction breakpoint is hit, a `stopped` event 
"
+//           "(with reason `instruction breakpoint`) is generated.\nClients "
+//           "should only call this request if the corresponding capability "
+//           "`supportsInstructionBreakpoints` is true.",
+//       "properties": {
+//         "command": { "type": "string", "enum": ["setInstructionBreakpoints"]
+//         }, "arguments": {"$ref":
+//         "#/definitions/SetInstructionBreakpointsArguments"}
+//       },
+//       "required": [ "command", "arguments" ]
+//     }
+//   ]
+// },
+// "SetInstructionBreakpointsArguments": {
+//   "type": "object",
+//   "description": "Arguments for `setInstructionBreakpoints` request",
+//   "properties": {
+//     "breakpoints": {
+//       "type": "array",
+//       "items": {"$ref": "#/definitions/InstructionBreakpoint"},
+//       "description": "The instruction references of the breakpoints"
+//     }
+//   },
+//   "required": ["breakpoints"]
+// },
+// "SetInstructionBreakpointsResponse": {
+//   "allOf": [
+//     {"$ref": "#/definitions/Response"},
+//     {
+//       "type": "object",
+//       "description": "Response to `setInstructionBreakpoints` request",
+//       "properties": {
+//         "body": {
+//           "type": "object",
+//           "properties": {
+//             "breakpoints": {
+//               "type": "array",
+//               "items": {"$ref": "#/definitions/Breakpoint"},
+//               "description":
+//                   "Information about the breakpoints. The array elements
+//                   " "correspond to the elements of the `breakpoints`
+//                   array."
+//             }
+//           },
+//           "required": ["breakpoints"]
+//         }
+//       },
+//       "required": ["body"]
+//     }
+//   ]
+// },
+// "InstructionBreakpoint": {
+//   "type": "object",
+//   "description": "Properties of a breakpoint passed to the "
+//                   "`setInstructionBreakpoints` request",
+//   "properties": {
+//     "instructionReference": {
+//       "type": "string",
+//       "description" :
+//           "The instruction reference of the breakpoint.\nThis should be a "
+//           "memory or instruction pointer reference from an
+//           `EvaluateResponse`, "
+//           "`Variable`, `StackFrame`, `GotoTarget`, or `Breakpoint`."
+//     },
+//     "offset": {
+//       "type": "integer",
+//       "description": "The offset from the instruction reference in "
+//                       "bytes.\nThis can be negative."
+//     },
+//     "condition": {
+//       "type": "string",
+//       "description": "An expression for conditional breakpoints.\nIt is only
+//       "
+//                       "honored by a debug adapter if the corresponding "
+//                       "capability `supportsConditionalBreakpoints` is true."
+//     },
+//     "hitCondition": {
+//       "type": "string",
+//       "description": "An expression that controls how many hits of the "
+//                       "breakpoint are ignored.\nThe debug adapter is 
expected
+//                       " "to interpret the expression as needed.\nThe
+//                       attribute " "is only honored by a debug adapter if the
+//                       corresponding " "capability
+//                       `supportsHitConditionalBreakpoints` is true."
+//     },
+//     "mode": {
+//       "type": "string",
+//       "description": "The mode of this breakpoint. If defined, this must be
+//       "
+//                       "one of the `breakpointModes` the debug adapter "
+//                       "advertised in its `Capabilities`."
+//     }
+//   },
+//   "required": ["instructionReference"]
+// },
+// "Breakpoint": {
+//   "type": "object",
+//   "description" :
+//       "Information about a breakpoint created in `setBreakpoints`, "
+//       "`setFunctionBreakpoints`, `setInstructionBreakpoints`, or "
+//       "`setDataBreakpoints` requests.",
+//   "properties": {
+//     "id": {
+//       "type": "integer",
+//       "description" :
+//           "The identifier for the breakpoint. It is needed if breakpoint
+//           " "events are used to update or remove breakpoints."
+//     },
+//     "verified": {
+//       "type": "boolean",
+//       "description": "If true, the breakpoint could be set (but not "
+//                       "necessarily at the desired location)."
+//     },
+//     "message": {
+//       "type": "string",
+//       "description": "A message about the state of the breakpoint.\nThis
+//       "
+//                       "is shown to the user and can be used to explain
+//                       why " "a breakpoint could not be verified."
+//     },
+//     "source": {
+//       "$ref": "#/definitions/Source",
+//       "description": "The source where the breakpoint is located."
+//     },
+//     "line": {
+//       "type": "integer",
+//       "description" :
+//           "The start line of the actual range covered by the breakpoint."
+//     },
+//     "column": {
+//       "type": "integer",
+//       "description" :
+//           "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."
+//     },
+//     "endLine": {
+//       "type": "integer",
+//       "description" :
+//           "The end line of the actual range covered by the breakpoint."
+//     },
+//     "endColumn": {
+//       "type": "integer",
+//       "description" :
+//           "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.\nIf
+//           " "no end line is given, then the end column is assumed to be
+//           in " "the start line."
+//     },
+//     "instructionReference": {
+//       "type": "string",
+//       "description": "A memory reference to where the breakpoint is
+//       set."
+//     },
+//     "offset": {
+//       "type": "integer",
+//       "description": "The offset from the instruction reference.\nThis "
+//                       "can be negative."
+//     },
+//     "reason": {
+//       "type": "string",
+//       "description" :
+//           "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.
+//           Possible " "values include:\n\n- `pending`: Indicates a
+//           breakpoint might be " "verified in the future, but the adapter
+//           cannot verify it in the " "current state.\n - `failed`:
+//           Indicates a breakpoint was not " "able to be verified, and the
+//           adapter does not believe it can be " "verified without
+//           intervention.",
+//       "enum": [ "pending", "failed" ]
+//     }
+//   },
+//   "required": ["verified"]
+// },
+void SetInstructionBreakpointsRequestHandler::operator()(
+    const llvm::json::Object &request) {
+  llvm::json::Object response;
+  llvm::json::Array response_breakpoints;
+  llvm::json::Object body;
+  FillResponse(request, response);
+
+  const auto *arguments = request.getObject("arguments");
+  const auto *breakpoints = arguments->getArray("breakpoints");
+
+  // Disable any instruction breakpoints that aren't in this request.
+  // There is no call to remove instruction breakpoints other than calling this
+  // function with a smaller or empty "breakpoints" list.
+  llvm::DenseSet<lldb::addr_t> seen;
+  for (const auto &addr : dap.instruction_breakpoints)
+    seen.insert(addr.first);
+
+  for (const auto &bp : *breakpoints) {
+    const auto *bp_obj = bp.getAsObject();
+    if (!bp_obj)
+      continue;
+    // Read instruction breakpoint request.
+    InstructionBreakpoint inst_bp(dap, *bp_obj);
+    const auto [iv, inserted] = dap.instruction_breakpoints.try_emplace(
+        inst_bp.instructionAddressReference, dap, *bp_obj);
+    if (inserted)
+      iv->second.SetBreakpoint();
+    else
+      iv->second.UpdateBreakpoint(inst_bp);
+    AppendBreakpoint(&iv->second, response_breakpoints);
+    seen.erase(inst_bp.instructionAddressReference);
+  }
+
+  for (const auto &addr : seen) {
+    auto inst_bp = dap.instruction_breakpoints.find(addr);
+    if (inst_bp == dap.instruction_breakpoints.end())
+      continue;
+    dap.target.BreakpointDelete(inst_bp->second.bp.GetID());
+    dap.instruction_breakpoints.erase(addr);
+  }
+
+  body.try_emplace("breakpoints", std::move(response_breakpoints));
+  response.try_emplace("body", std::move(body));
+  dap.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+} // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index 632629d56232c..fd4615897841c 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -18,8 +18,6 @@
 #include "lldb/API/SBEvent.h"
 #include "lldb/API/SBFile.h"
 #include "lldb/API/SBInstruction.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBMemoryRegionInfo.h"
 #include "lldb/API/SBStream.h"
 #include "lldb/Host/Config.h"
 #include "lldb/Host/MainLoop.h"
@@ -395,636 +393,6 @@ void request_scopes(DAP &dap, const llvm::json::Object 
&request) {
   dap.SendJSON(llvm::json::Value(std::move(response)));
 }
 
-// "SetBreakpointsRequest": {
-//   "allOf": [ { "$ref": "#/definitions/Request" }, {
-//     "type": "object",
-//     "description": "SetBreakpoints request; value of command field is
-//     'setBreakpoints'. Sets multiple breakpoints for a single source and
-//     clears all previous breakpoints in that source. To clear all breakpoint
-//     for a source, specify an empty array. When a breakpoint is hit, a
-//     StoppedEvent (event type 'breakpoint') is generated.", "properties": {
-//       "command": {
-//         "type": "string",
-//         "enum": [ "setBreakpoints" ]
-//       },
-//       "arguments": {
-//         "$ref": "#/definitions/SetBreakpointsArguments"
-//       }
-//     },
-//     "required": [ "command", "arguments"  ]
-//   }]
-// },
-// "SetBreakpointsArguments": {
-//   "type": "object",
-//   "description": "Arguments for 'setBreakpoints' request.",
-//   "properties": {
-//     "source": {
-//       "$ref": "#/definitions/Source",
-//       "description": "The source location of the breakpoints; either
-//       source.path or source.reference must be specified."
-//     },
-//     "breakpoints": {
-//       "type": "array",
-//       "items": {
-//         "$ref": "#/definitions/SourceBreakpoint"
-//       },
-//       "description": "The code locations of the breakpoints."
-//     },
-//     "lines": {
-//       "type": "array",
-//       "items": {
-//         "type": "integer"
-//       },
-//       "description": "Deprecated: The code locations of the breakpoints."
-//     },
-//     "sourceModified": {
-//       "type": "boolean",
-//       "description": "A value of true indicates that the underlying source
-//       has been modified which results in new breakpoint locations."
-//     }
-//   },
-//   "required": [ "source" ]
-// },
-// "SetBreakpointsResponse": {
-//   "allOf": [ { "$ref": "#/definitions/Response" }, {
-//     "type": "object",
-//     "description": "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') in the
-//     SetBreakpointsArguments.", "properties": {
-//       "body": {
-//         "type": "object",
-//         "properties": {
-//           "breakpoints": {
-//             "type": "array",
-//             "items": {
-//               "$ref": "#/definitions/Breakpoint"
-//             },
-//             "description": "Information about the breakpoints. The array
-//             elements are in the same order as the elements of the
-//             'breakpoints' (or the deprecated 'lines') in the
-//             SetBreakpointsArguments."
-//           }
-//         },
-//         "required": [ "breakpoints" ]
-//       }
-//     },
-//     "required": [ "body" ]
-//   }]
-// },
-// "SourceBreakpoint": {
-//   "type": "object",
-//   "description": "Properties of a breakpoint or logpoint passed to the
-//   setBreakpoints request.", "properties": {
-//     "line": {
-//       "type": "integer",
-//       "description": "The source line of the breakpoint or logpoint."
-//     },
-//     "column": {
-//       "type": "integer",
-//       "description": "An optional source column of the breakpoint."
-//     },
-//     "condition": {
-//       "type": "string",
-//       "description": "An optional expression for conditional breakpoints."
-//     },
-//     "hitCondition": {
-//       "type": "string",
-//       "description": "An optional expression that controls how many hits of
-//       the breakpoint are ignored. The backend is expected to interpret the
-//       expression as needed."
-//     },
-//     "logMessage": {
-//       "type": "string",
-//       "description": "If this attribute exists and is non-empty, the backend
-//       must not 'break' (stop) but log the message instead. Expressions 
within
-//       {} are interpolated."
-//     }
-//   },
-//   "required": [ "line" ]
-// }
-void request_setBreakpoints(DAP &dap, const llvm::json::Object &request) {
-  llvm::json::Object response;
-  lldb::SBError error;
-  FillResponse(request, response);
-  const auto *arguments = request.getObject("arguments");
-  const auto *source = arguments->getObject("source");
-  const auto path = GetString(source, "path");
-  const auto *breakpoints = arguments->getArray("breakpoints");
-  llvm::json::Array response_breakpoints;
-
-  // Decode the source breakpoint infos for this "setBreakpoints" request
-  SourceBreakpointMap request_bps;
-  // "breakpoints" may be unset, in which case we treat it the same as being 
set
-  // to an empty array.
-  if (breakpoints) {
-    for (const auto &bp : *breakpoints) {
-      const auto *bp_obj = bp.getAsObject();
-      if (bp_obj) {
-        SourceBreakpoint src_bp(dap, *bp_obj);
-        std::pair<uint32_t, uint32_t> bp_pos(src_bp.line, src_bp.column);
-        request_bps.try_emplace(bp_pos, src_bp);
-        const auto [iv, inserted] =
-            dap.source_breakpoints[path].try_emplace(bp_pos, src_bp);
-        // We check if this breakpoint already exists to update it
-        if (inserted)
-          iv->getSecond().SetBreakpoint(path.data());
-        else
-          iv->getSecond().UpdateBreakpoint(src_bp);
-        AppendBreakpoint(&iv->getSecond(), response_breakpoints, path,
-                         src_bp.line);
-      }
-    }
-  }
-
-  // Delete any breakpoints in this source file that aren't in the
-  // request_bps set. There is no call to remove breakpoints other than
-  // calling this function with a smaller or empty "breakpoints" list.
-  auto old_src_bp_pos = dap.source_breakpoints.find(path);
-  if (old_src_bp_pos != dap.source_breakpoints.end()) {
-    for (auto &old_bp : old_src_bp_pos->second) {
-      auto request_pos = request_bps.find(old_bp.first);
-      if (request_pos == request_bps.end()) {
-        // This breakpoint no longer exists in this source file, delete it
-        dap.target.BreakpointDelete(old_bp.second.bp.GetID());
-        old_src_bp_pos->second.erase(old_bp.first);
-      }
-    }
-  }
-
-  llvm::json::Object body;
-  body.try_emplace("breakpoints", std::move(response_breakpoints));
-  response.try_emplace("body", std::move(body));
-  dap.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-// "SetExceptionBreakpointsRequest": {
-//   "allOf": [ { "$ref": "#/definitions/Request" }, {
-//     "type": "object",
-//     "description": "SetExceptionBreakpoints request; value of command field
-//     is 'setExceptionBreakpoints'. The request configures the debuggers
-//     response to thrown exceptions. If an exception is configured to break, a
-//     StoppedEvent is fired (event type 'exception').", "properties": {
-//       "command": {
-//         "type": "string",
-//         "enum": [ "setExceptionBreakpoints" ]
-//       },
-//       "arguments": {
-//         "$ref": "#/definitions/SetExceptionBreakpointsArguments"
-//       }
-//     },
-//     "required": [ "command", "arguments"  ]
-//   }]
-// },
-// "SetExceptionBreakpointsArguments": {
-//   "type": "object",
-//   "description": "Arguments for 'setExceptionBreakpoints' request.",
-//   "properties": {
-//     "filters": {
-//       "type": "array",
-//       "items": {
-//         "type": "string"
-//       },
-//       "description": "IDs of checked exception options. The set of IDs is
-//       returned via the 'exceptionBreakpointFilters' capability."
-//     },
-//     "exceptionOptions": {
-//       "type": "array",
-//       "items": {
-//         "$ref": "#/definitions/ExceptionOptions"
-//       },
-//       "description": "Configuration options for selected exceptions."
-//     }
-//   },
-//   "required": [ "filters" ]
-// },
-// "SetExceptionBreakpointsResponse": {
-//   "allOf": [ { "$ref": "#/definitions/Response" }, {
-//     "type": "object",
-//     "description": "Response to 'setExceptionBreakpoints' request. This is
-//     just an acknowledgement, so no body field is required."
-//   }]
-// }
-void request_setExceptionBreakpoints(DAP &dap,
-                                     const llvm::json::Object &request) {
-  llvm::json::Object response;
-  lldb::SBError error;
-  FillResponse(request, response);
-  const auto *arguments = request.getObject("arguments");
-  const auto *filters = arguments->getArray("filters");
-  // Keep a list of any exception breakpoint filter names that weren't set
-  // so we can clear any exception breakpoints if needed.
-  std::set<std::string> unset_filters;
-  for (const auto &bp : *dap.exception_breakpoints)
-    unset_filters.insert(bp.filter);
-
-  for (const auto &value : *filters) {
-    const auto filter = GetAsString(value);
-    auto *exc_bp = dap.GetExceptionBreakpoint(std::string(filter));
-    if (exc_bp) {
-      exc_bp->SetBreakpoint();
-      unset_filters.erase(std::string(filter));
-    }
-  }
-  for (const auto &filter : unset_filters) {
-    auto *exc_bp = dap.GetExceptionBreakpoint(filter);
-    if (exc_bp)
-      exc_bp->ClearBreakpoint();
-  }
-  dap.SendJSON(llvm::json::Value(std::move(response)));
-}
-
-// "SetFunctionBreakpointsRequest": {
-//   "allOf": [ { "$ref": "#/definitions/Request" }, {
-//     "type": "object",
-//     "description": "SetFunctionBreakpoints request; value of command field 
is
-//     'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
-//     all previous function breakpoints. To clear all function breakpoint,
-//     specify an empty array. When a function breakpoint is hit, a 
StoppedEvent
-//     (event type 'function breakpoint') is generated.", "properties": {
-//       "command": {
-//         "type": "string",
-//         "enum": [ "setFunctionBreakpoints" ]
-//       },
-//       "arguments": {
-//         "$ref": "#/definitions/SetFunctionBreakpointsArguments"
-//       }
-//     },
-//     "required": [ "command", "arguments"  ]
-//   }]
-// },
-// "SetFunctionBreakpointsArguments": {
-//   "type": "object",
-//   "description": "Arguments for 'setFunctionBreakpoints' request.",
-//   "properties": {
-//     "breakpoints": {
-//       "type": "array",
-//       "items": {
-//         "$ref": "#/definitions/FunctionBreakpoint"
-//       },
-//       "description": "The function names of the breakpoints."
-//     }
-//   },
-//   "required": [ "breakpoints" ]
-// },
-// "FunctionBreakpoint": {
-//   "type": "object",
-//   "description": "Properties of a breakpoint passed to the
-//   setFunctionBreakpoints request.", "properties": {
-//     "name": {
-//       "type": "string",
-//       "description": "The name of the function."
-//     },
-//     "condition": {
-//       "type": "string",
-//       "description": "An optional expression for conditional breakpoints."
-//     },
-//     "hitCondition": {
-//       "type": "string",
-//       "description": "An optional expression that controls how many hits of
-//       the breakpoint are ignored. The backend is expected to interpret the
-//       expression as needed."
-//     }
-//   },
-//   "required": [ "name" ]
-// },
-// "SetFunctionBreakpointsResponse": {
-//   "allOf": [ { "$ref": "#/definitions/Response" }, {
-//     "type": "object",
-//     "description": "Response to 'setFunctionBreakpoints' request. Returned 
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 breakpoints. The array
-//             elements correspond to the elements of the 'breakpoints' array."
-//           }
-//         },
-//         "required": [ "breakpoints" ]
-//       }
-//     },
-//     "required": [ "body" ]
-//   }]
-// }
-void request_setFunctionBreakpoints(DAP &dap,
-                                    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;
-
-  // Disable any function breakpoints that aren't in this request.
-  // There is no call to remove function breakpoints other than calling this
-  // function with a smaller or empty "breakpoints" list.
-  const auto name_iter = dap.function_breakpoints.keys();
-  llvm::DenseSet<llvm::StringRef> seen(name_iter.begin(), name_iter.end());
-  for (const auto &value : *breakpoints) {
-    const auto *bp_obj = value.getAsObject();
-    if (!bp_obj)
-      continue;
-    FunctionBreakpoint fn_bp(dap, *bp_obj);
-    const auto [it, inserted] =
-        dap.function_breakpoints.try_emplace(fn_bp.functionName, dap, *bp_obj);
-    if (inserted)
-      it->second.SetBreakpoint();
-    else
-      it->second.UpdateBreakpoint(fn_bp);
-
-    AppendBreakpoint(&it->second, response_breakpoints);
-    seen.erase(fn_bp.functionName);
-  }
-
-  // Remove any breakpoints that are no longer in our list
-  for (const auto &name : seen) {
-    auto fn_bp = dap.function_breakpoints.find(name);
-    if (fn_bp == dap.function_breakpoints.end())
-      continue;
-    dap.target.BreakpointDelete(fn_bp->second.bp.GetID());
-    dap.function_breakpoints.erase(name);
-  }
-
-  llvm::json::Object body;
-  body.try_emplace("breakpoints", std::move(response_breakpoints));
-  response.try_emplace("body", std::move(body));
-  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(DAP &dap, 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 = dap.GetLLDBFrame(*arguments);
-  lldb::SBValue variable = FindVariable(dap, variablesReference, name);
-  std::string addr, size;
-
-  if (variable.IsValid()) {
-    lldb::addr_t load_addr = variable.GetLoadAddress();
-    size_t byte_size = variable.GetByteSize();
-    if (load_addr == LLDB_INVALID_ADDRESS) {
-      body.try_emplace("dataId", nullptr);
-      body.try_emplace("description",
-                       "does not exist in memory, its location is " +
-                           std::string(variable.GetLocation()));
-    } else if (byte_size == 0) {
-      body.try_emplace("dataId", nullptr);
-      body.try_emplace("description", "variable size is 0");
-    } else {
-      addr = llvm::utohexstr(load_addr);
-      size = llvm::utostr(byte_size);
-    }
-  } else if (variablesReference == 0 && frame.IsValid()) {
-    lldb::SBValue value = frame.EvaluateExpression(name.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 {
-      uint64_t load_addr = value.GetValueAsUnsigned();
-      lldb::SBData data = value.GetPointeeData();
-      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())) {
-            body.try_emplace("dataId", nullptr);
-            body.try_emplace("description",
-                             "memory region for address " + addr +
-                                 " has no read or write permissions");
-          }
-        }
-      } else {
-        body.try_emplace("dataId", nullptr);
-        body.try_emplace("description",
-                         "unable to get byte size for expression: " +
-                             name.str());
-      }
-    }
-  } else {
-    body.try_emplace("dataId", nullptr);
-    body.try_emplace("description", "variable not found: " + name.str());
-  }
-
-  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));
-  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(DAP &dap, 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;
-  dap.target.DeleteAllWatchpoints();
-  std::vector<Watchpoint> watchpoints;
-  if (breakpoints) {
-    for (const auto &bp : *breakpoints) {
-      const auto *bp_obj = bp.getAsObject();
-      if (bp_obj)
-        watchpoints.emplace_back(dap, *bp_obj);
-    }
-  }
-  // If two watchpoints start at the same address, the latter overwrite the
-  // former. So, we only enable those at first-seen addresses when iterating
-  // backward.
-  std::set<lldb::addr_t> addresses;
-  for (auto iter = watchpoints.rbegin(); iter != watchpoints.rend(); ++iter) {
-    if (addresses.count(iter->addr) == 0) {
-      iter->SetWatchpoint();
-      addresses.insert(iter->addr);
-    }
-  }
-  for (auto wp : watchpoints)
-    AppendBreakpoint(&wp, response_breakpoints);
-
-  llvm::json::Object body;
-  body.try_emplace("breakpoints", std::move(response_breakpoints));
-  response.try_emplace("body", std::move(body));
-  dap.SendJSON(llvm::json::Value(std::move(response)));
-}
-
 // "SourceRequest": {
 //   "allOf": [ { "$ref": "#/definitions/Request" }, {
 //     "type": "object",
@@ -2081,245 +1449,13 @@ void request_readMemory(DAP &dap, const 
llvm::json::Object &request) {
   dap.SendJSON(llvm::json::Value(std::move(response)));
 }
 
-// "SetInstructionBreakpointsRequest": {
-//   "allOf": [
-//     {"$ref": "#/definitions/Request"},
-//     {
-//       "type": "object",
-//       "description" :
-//           "Replaces all existing instruction breakpoints. Typically, "
-//           "instruction breakpoints would be set from a disassembly window. "
-//           "\nTo clear all instruction breakpoints, specify an empty "
-//           "array.\nWhen an instruction breakpoint is hit, a `stopped` event 
"
-//           "(with reason `instruction breakpoint`) is generated.\nClients "
-//           "should only call this request if the corresponding capability "
-//           "`supportsInstructionBreakpoints` is true.",
-//       "properties": {
-//         "command": { "type": "string", "enum": ["setInstructionBreakpoints"]
-//         }, "arguments": {"$ref":
-//         "#/definitions/SetInstructionBreakpointsArguments"}
-//       },
-//       "required": [ "command", "arguments" ]
-//     }
-//   ]
-// },
-// "SetInstructionBreakpointsArguments": {
-//   "type": "object",
-//   "description": "Arguments for `setInstructionBreakpoints` request",
-//   "properties": {
-//     "breakpoints": {
-//       "type": "array",
-//       "items": {"$ref": "#/definitions/InstructionBreakpoint"},
-//       "description": "The instruction references of the breakpoints"
-//     }
-//   },
-//   "required": ["breakpoints"]
-// },
-// "SetInstructionBreakpointsResponse": {
-//   "allOf": [
-//     {"$ref": "#/definitions/Response"},
-//     {
-//       "type": "object",
-//       "description": "Response to `setInstructionBreakpoints` request",
-//       "properties": {
-//         "body": {
-//           "type": "object",
-//           "properties": {
-//             "breakpoints": {
-//               "type": "array",
-//               "items": {"$ref": "#/definitions/Breakpoint"},
-//               "description":
-//                   "Information about the breakpoints. The array elements
-//                   " "correspond to the elements of the `breakpoints`
-//                   array."
-//             }
-//           },
-//           "required": ["breakpoints"]
-//         }
-//       },
-//       "required": ["body"]
-//     }
-//   ]
-// },
-// "InstructionBreakpoint": {
-//   "type": "object",
-//   "description": "Properties of a breakpoint passed to the "
-//                   "`setInstructionBreakpoints` request",
-//   "properties": {
-//     "instructionReference": {
-//       "type": "string",
-//       "description" :
-//           "The instruction reference of the breakpoint.\nThis should be a "
-//           "memory or instruction pointer reference from an
-//           `EvaluateResponse`, "
-//           "`Variable`, `StackFrame`, `GotoTarget`, or `Breakpoint`."
-//     },
-//     "offset": {
-//       "type": "integer",
-//       "description": "The offset from the instruction reference in "
-//                       "bytes.\nThis can be negative."
-//     },
-//     "condition": {
-//       "type": "string",
-//       "description": "An expression for conditional breakpoints.\nIt is only
-//       "
-//                       "honored by a debug adapter if the corresponding "
-//                       "capability `supportsConditionalBreakpoints` is true."
-//     },
-//     "hitCondition": {
-//       "type": "string",
-//       "description": "An expression that controls how many hits of the "
-//                       "breakpoint are ignored.\nThe debug adapter is 
expected
-//                       " "to interpret the expression as needed.\nThe
-//                       attribute " "is only honored by a debug adapter if the
-//                       corresponding " "capability
-//                       `supportsHitConditionalBreakpoints` is true."
-//     },
-//     "mode": {
-//       "type": "string",
-//       "description": "The mode of this breakpoint. If defined, this must be
-//       "
-//                       "one of the `breakpointModes` the debug adapter "
-//                       "advertised in its `Capabilities`."
-//     }
-//   },
-//   "required": ["instructionReference"]
-// },
-// "Breakpoint": {
-//   "type": "object",
-//   "description" :
-//       "Information about a breakpoint created in `setBreakpoints`, "
-//       "`setFunctionBreakpoints`, `setInstructionBreakpoints`, or "
-//       "`setDataBreakpoints` requests.",
-//   "properties": {
-//     "id": {
-//       "type": "integer",
-//       "description" :
-//           "The identifier for the breakpoint. It is needed if breakpoint
-//           " "events are used to update or remove breakpoints."
-//     },
-//     "verified": {
-//       "type": "boolean",
-//       "description": "If true, the breakpoint could be set (but not "
-//                       "necessarily at the desired location)."
-//     },
-//     "message": {
-//       "type": "string",
-//       "description": "A message about the state of the breakpoint.\nThis
-//       "
-//                       "is shown to the user and can be used to explain
-//                       why " "a breakpoint could not be verified."
-//     },
-//     "source": {
-//       "$ref": "#/definitions/Source",
-//       "description": "The source where the breakpoint is located."
-//     },
-//     "line": {
-//       "type": "integer",
-//       "description" :
-//           "The start line of the actual range covered by the breakpoint."
-//     },
-//     "column": {
-//       "type": "integer",
-//       "description" :
-//           "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."
-//     },
-//     "endLine": {
-//       "type": "integer",
-//       "description" :
-//           "The end line of the actual range covered by the breakpoint."
-//     },
-//     "endColumn": {
-//       "type": "integer",
-//       "description" :
-//           "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.\nIf
-//           " "no end line is given, then the end column is assumed to be
-//           in " "the start line."
-//     },
-//     "instructionReference": {
-//       "type": "string",
-//       "description": "A memory reference to where the breakpoint is
-//       set."
-//     },
-//     "offset": {
-//       "type": "integer",
-//       "description": "The offset from the instruction reference.\nThis "
-//                       "can be negative."
-//     },
-//     "reason": {
-//       "type": "string",
-//       "description" :
-//           "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.
-//           Possible " "values include:\n\n- `pending`: Indicates a
-//           breakpoint might be " "verified in the future, but the adapter
-//           cannot verify it in the " "current state.\n - `failed`:
-//           Indicates a breakpoint was not " "able to be verified, and the
-//           adapter does not believe it can be " "verified without
-//           intervention.",
-//       "enum": [ "pending", "failed" ]
-//     }
-//   },
-//   "required": ["verified"]
-// },
-void request_setInstructionBreakpoints(DAP &dap,
-                                       const llvm::json::Object &request) {
-  llvm::json::Object response;
-  llvm::json::Array response_breakpoints;
-  llvm::json::Object body;
-  FillResponse(request, response);
-
-  const auto *arguments = request.getObject("arguments");
-  const auto *breakpoints = arguments->getArray("breakpoints");
-
-  // Disable any instruction breakpoints that aren't in this request.
-  // There is no call to remove instruction breakpoints other than calling this
-  // function with a smaller or empty "breakpoints" list.
-  llvm::DenseSet<lldb::addr_t> seen;
-  for (const auto &addr : dap.instruction_breakpoints)
-    seen.insert(addr.first);
-
-  for (const auto &bp : *breakpoints) {
-    const auto *bp_obj = bp.getAsObject();
-    if (!bp_obj)
-      continue;
-    // Read instruction breakpoint request.
-    InstructionBreakpoint inst_bp(dap, *bp_obj);
-    const auto [iv, inserted] = dap.instruction_breakpoints.try_emplace(
-        inst_bp.instructionAddressReference, dap, *bp_obj);
-    if (inserted)
-      iv->second.SetBreakpoint();
-    else
-      iv->second.UpdateBreakpoint(inst_bp);
-    AppendBreakpoint(&iv->second, response_breakpoints);
-    seen.erase(inst_bp.instructionAddressReference);
-  }
-
-  for (const auto &addr : seen) {
-    auto inst_bp = dap.instruction_breakpoints.find(addr);
-    if (inst_bp == dap.instruction_breakpoints.end())
-      continue;
-    dap.target.BreakpointDelete(inst_bp->second.bp.GetID());
-    dap.instruction_breakpoints.erase(addr);
-  }
-
-  body.try_emplace("breakpoints", std::move(response_breakpoints));
-  response.try_emplace("body", std::move(body));
-  dap.SendJSON(llvm::json::Value(std::move(response)));
-}
-
 void RegisterRequestCallbacks(DAP &dap) {
   dap.RegisterRequest<AttachRequestHandler>();
   dap.RegisterRequest<BreakpointLocationsRequestHandler>();
   dap.RegisterRequest<CompletionsRequestHandler>();
   dap.RegisterRequest<ConfigurationDoneRequestHandler>();
   dap.RegisterRequest<ContinueRequestHandler>();
+  dap.RegisterRequest<DataBreakpointInfoRequestHandler>();
   dap.RegisterRequest<DisconnectRequestHandler>();
   dap.RegisterRequest<EvaluateRequestHandler>();
   dap.RegisterRequest<ExceptionInfoRequestHandler>();
@@ -2327,6 +1463,11 @@ void RegisterRequestCallbacks(DAP &dap) {
   dap.RegisterRequest<LaunchRequestHandler>();
   dap.RegisterRequest<NextRequestHandler>();
   dap.RegisterRequest<RestartRequestHandler>();
+  dap.RegisterRequest<SetBreakpointsRequestHandler>();
+  dap.RegisterRequest<SetDataBreakpointsRequestHandler>();
+  dap.RegisterRequest<SetExceptionBreakpointsRequestHandler>();
+  dap.RegisterRequest<SetFunctionBreakpointsRequestHandler>();
+  dap.RegisterRequest<SetInstructionBreakpointsRequestHandler>();
   dap.RegisterRequest<StepInRequestHandler>();
   dap.RegisterRequest<StepInTargetsRequestHandler>();
   dap.RegisterRequest<StepOutRequestHandler>();
@@ -2340,13 +1481,6 @@ void RegisterRequestCallbacks(DAP &dap) {
 
   dap.RegisterRequestCallback("pause", request_pause);
   dap.RegisterRequestCallback("scopes", request_scopes);
-  dap.RegisterRequestCallback("setBreakpoints", request_setBreakpoints);
-  dap.RegisterRequestCallback("setExceptionBreakpoints",
-                              request_setExceptionBreakpoints);
-  dap.RegisterRequestCallback("setFunctionBreakpoints",
-                              request_setFunctionBreakpoints);
-  dap.RegisterRequestCallback("dataBreakpointInfo", 
request_dataBreakpointInfo);
-  dap.RegisterRequestCallback("setDataBreakpoints", 
request_setDataBreakpoints);
   dap.RegisterRequestCallback("setVariable", request_setVariable);
   dap.RegisterRequestCallback("source", request_source);
   dap.RegisterRequestCallback("stackTrace", request_stackTrace);
@@ -2355,8 +1489,6 @@ void RegisterRequestCallbacks(DAP &dap) {
   dap.RegisterRequestCallback("locations", request_locations);
   dap.RegisterRequestCallback("disassemble", request_disassemble);
   dap.RegisterRequestCallback("readMemory", request_readMemory);
-  dap.RegisterRequestCallback("setInstructionBreakpoints",
-                              request_setInstructionBreakpoints);
 }
 
 } // anonymous namespace

>From 8f39c7725b00f3e263868cae4651ab852ac74dcd Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jo...@devlieghere.com>
Date: Mon, 24 Feb 2025 14:20:15 -0600
Subject: [PATCH 2/3] Move helpers into Variable

---
 lldb/tools/lldb-dap/DAP.cpp                   | 54 +++++++++++++++++
 lldb/tools/lldb-dap/DAP.h                     |  4 ++
 .../DataBreakpointInfoRequestHandler.cpp      |  2 +-
 .../tools/lldb-dap/Handler/RequestHandler.cpp | 55 -----------------
 lldb/tools/lldb-dap/Handler/RequestHandler.h  |  3 -
 lldb/tools/lldb-dap/lldb-dap.cpp              | 59 +------------------
 6 files changed, 61 insertions(+), 116 deletions(-)

diff --git a/lldb/tools/lldb-dap/DAP.cpp b/lldb/tools/lldb-dap/DAP.cpp
index 9b22b60a68d94..c9487dd89b5dc 100644
--- a/lldb/tools/lldb-dap/DAP.cpp
+++ b/lldb/tools/lldb-dap/DAP.cpp
@@ -1201,4 +1201,58 @@ DAP::GetInstructionBPFromStopReason(lldb::SBThread 
&thread) {
   return inst_bp;
 }
 
+lldb::SBValueList *Variables::GetTopLevelScope(int64_t variablesReference) {
+  switch (variablesReference) {
+  case VARREF_LOCALS:
+    return &locals;
+  case VARREF_GLOBALS:
+    return &globals;
+  case VARREF_REGS:
+    return &registers;
+  default:
+    return nullptr;
+  }
+}
+
+lldb::SBValue Variables::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 = 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;
+}
+
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/DAP.h b/lldb/tools/lldb-dap/DAP.h
index 18de39838f218..ca26ea1b9a5de 100644
--- a/lldb/tools/lldb-dap/DAP.h
+++ b/lldb/tools/lldb-dap/DAP.h
@@ -116,6 +116,10 @@ struct Variables {
   /// \return variableReference assigned to this expandable variable.
   int64_t InsertVariable(lldb::SBValue variable, bool is_permanent);
 
+  lldb::SBValueList *GetTopLevelScope(int64_t variablesReference);
+
+  lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef 
name);
+
   /// Clear all scope variables and non-permanent expandable variables.
   void Clear();
 };
diff --git a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
index 519a9c728e4b3..0d007ee52e07f 100644
--- a/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp
@@ -119,7 +119,7 @@ void DataBreakpointInfoRequestHandler::operator()(
       GetUnsigned(arguments, "variablesReference", 0);
   llvm::StringRef name = GetString(arguments, "name");
   lldb::SBFrame frame = dap.GetLLDBFrame(*arguments);
-  lldb::SBValue variable = FindVariable(variablesReference, name);
+  lldb::SBValue variable = dap.variables.FindVariable(variablesReference, 
name);
   std::string addr, size;
 
   if (variable.IsValid()) {
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index de313eb02a24a..f9502e09846d4 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -232,59 +232,4 @@ bool RequestHandler::HasInstructionGranularity(
   return false;
 }
 
-lldb::SBValueList *
-RequestHandler::GetTopLevelScope(int64_t variablesReference) {
-  switch (variablesReference) {
-  case VARREF_LOCALS:
-    return &dap.variables.locals;
-  case VARREF_GLOBALS:
-    return &dap.variables.globals;
-  case VARREF_REGS:
-    return &dap.variables.registers;
-  default:
-    return nullptr;
-  }
-}
-
-lldb::SBValue RequestHandler::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 = 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;
-}
-
 } // namespace lldb_dap
diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.h 
b/lldb/tools/lldb-dap/Handler/RequestHandler.h
index a30e0dcc2bd04..9ca03ea25971d 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.h
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.h
@@ -52,9 +52,6 @@ class RequestHandler {
   // Check if the step-granularity is `instruction`.
   bool HasInstructionGranularity(const llvm::json::Object &request);
 
-  lldb::SBValueList *GetTopLevelScope(int64_t variablesReference);
-  lldb::SBValue FindVariable(uint64_t variablesReference, llvm::StringRef 
name);
-
   /// @}
 
   DAP &dap;
diff --git a/lldb/tools/lldb-dap/lldb-dap.cpp b/lldb/tools/lldb-dap/lldb-dap.cpp
index fd4615897841c..b939c231e4d91 100644
--- a/lldb/tools/lldb-dap/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/lldb-dap.cpp
@@ -130,61 +130,6 @@ typedef void (*RequestCallback)(const llvm::json::Object 
&command);
 /// Page size used for reporting addtional frames in the 'stackTrace' request.
 constexpr int StackPageSize = 20;
 
-lldb::SBValueList *GetTopLevelScope(DAP &dap, int64_t variablesReference) {
-  switch (variablesReference) {
-  case VARREF_LOCALS:
-    return &dap.variables.locals;
-  case VARREF_GLOBALS:
-    return &dap.variables.globals;
-  case VARREF_REGS:
-    return &dap.variables.registers;
-  default:
-    return nullptr;
-  }
-}
-
-lldb::SBValue FindVariable(DAP &dap, uint64_t variablesReference,
-                           llvm::StringRef name) {
-  lldb::SBValue variable;
-  if (lldb::SBValueList *top_scope =
-          GetTopLevelScope(dap, 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 = 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;
-}
-
 // Fill in the stack frames of the thread.
 //
 // Threads stacks may contain runtime specific extended backtraces, when
@@ -741,7 +686,7 @@ void request_setVariable(DAP &dap, const llvm::json::Object 
&request) {
   if (id_value != UINT64_MAX) {
     variable = dap.variables.GetVariable(id_value);
   } else {
-    variable = FindVariable(dap, variablesReference, name);
+    variable = dap.variables.FindVariable(variablesReference, name);
   }
 
   if (variable.IsValid()) {
@@ -867,7 +812,7 @@ void request_variables(DAP &dap, const llvm::json::Object 
&request) {
     hex = GetBoolean(format, "hex", false);
 
   if (lldb::SBValueList *top_scope =
-          GetTopLevelScope(dap, variablesReference)) {
+          dap.variables.GetTopLevelScope(variablesReference)) {
     // variablesReference is one of our scopes, not an actual variable it is
     // asking for the list of args, locals or globals.
     int64_t start_idx = 0;

>From f8b6011d1d08caa250bb13b99200369d064853e2 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jo...@devlieghere.com>
Date: Mon, 24 Feb 2025 14:21:23 -0600
Subject: [PATCH 3/3] Fix missing newline in CMakeLists.txt

---
 lldb/tools/lldb-dap/CMakeLists.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lldb/tools/lldb-dap/CMakeLists.txt 
b/lldb/tools/lldb-dap/CMakeLists.txt
index c04b10861a4c5..49809ec1c2592 100644
--- a/lldb/tools/lldb-dap/CMakeLists.txt
+++ b/lldb/tools/lldb-dap/CMakeLists.txt
@@ -57,9 +57,10 @@ add_lldb_tool(lldb-dap
   Handler/SetDataBreakpointsRequestHandler.cpp
   Handler/SetExceptionBreakpointsRequestHandler.cpp
   Handler/SetFunctionBreakpointsRequestHandler.cpp
-  Handler/SetInstructionBreakpointsRequestHandler.cpp 
Handler/StepOutRequestHandler.cpp
+  Handler/SetInstructionBreakpointsRequestHandler.cpp
   Handler/StepInRequestHandler.cpp
   Handler/StepInTargetsRequestHandler.cpp
+  Handler/StepOutRequestHandler.cpp
   Handler/TestGetTargetBreakpointsRequestHandler.cpp
 
   LINK_LIBS

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to