Convert Breakpoint & Watchpoints structs to classes to provide proper access control. This is in preparation for adopting SBMutex to protect the underlying SBBreakpoint and SBWatchpoint.
140 lines
4.8 KiB
C++
140 lines
4.8 KiB
C++
//===-- 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) const {
|
|
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.GetFunctionName(), dap, *bp_obj);
|
|
if (inserted)
|
|
it->second.SetBreakpoint();
|
|
else
|
|
it->second.UpdateBreakpoint(fn_bp);
|
|
|
|
AppendBreakpoint(&it->second, response_breakpoints);
|
|
seen.erase(fn_bp.GetFunctionName());
|
|
}
|
|
|
|
// 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.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
|