1//===-- DataBreakpointInfoRequestHandler.cpp ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DAP.h"
10#include "EventHelper.h"
11#include "Protocol/ProtocolTypes.h"
12#include "RequestHandler.h"
13#include "lldb/API/SBMemoryRegionInfo.h"
14#include "llvm/ADT/StringExtras.h"
15#include <optional>
16
17namespace lldb_dap {
18
19/// Obtains information on a possible data breakpoint that could be set on an
20/// expression or variable. Clients should only call this request if the
21/// corresponding capability supportsDataBreakpoints is true.
22llvm::Expected<protocol::DataBreakpointInfoResponseBody>
23DataBreakpointInfoRequestHandler::Run(
24 const protocol::DataBreakpointInfoArguments &args) const {
25 protocol::DataBreakpointInfoResponseBody response;
26 lldb::SBFrame frame = dap.GetLLDBFrame(frame_id: args.frameId.value_or(UINT64_MAX));
27 lldb::SBValue variable = dap.variables.FindVariable(
28 variablesReference: args.variablesReference.value_or(u: 0), name: args.name);
29 std::string addr, size;
30
31 bool is_data_ok = true;
32 if (variable.IsValid()) {
33 lldb::addr_t load_addr = variable.GetLoadAddress();
34 size_t byte_size = variable.GetByteSize();
35 if (load_addr == LLDB_INVALID_ADDRESS) {
36 is_data_ok = false;
37 response.description = "does not exist in memory, its location is " +
38 std::string(variable.GetLocation());
39 } else if (byte_size == 0) {
40 is_data_ok = false;
41 response.description = "variable size is 0";
42 } else {
43 addr = llvm::utohexstr(X: load_addr);
44 size = llvm::utostr(X: byte_size);
45 }
46 } else if (args.variablesReference.value_or(u: 0) == 0 && frame.IsValid()) {
47 lldb::SBValue value = frame.EvaluateExpression(expr: args.name.c_str());
48 if (value.GetError().Fail()) {
49 lldb::SBError error = value.GetError();
50 const char *error_cstr = error.GetCString();
51 is_data_ok = false;
52 response.description = error_cstr && error_cstr[0]
53 ? std::string(error_cstr)
54 : "evaluation failed";
55 } else {
56 uint64_t load_addr = value.GetValueAsUnsigned();
57 lldb::SBData data = value.GetPointeeData();
58 if (data.IsValid()) {
59 size = llvm::utostr(X: data.GetByteSize());
60 addr = llvm::utohexstr(X: load_addr);
61 lldb::SBMemoryRegionInfo region;
62 lldb::SBError err =
63 dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region_info&: region);
64 // Only lldb-server supports "qMemoryRegionInfo". So, don't fail this
65 // request if SBProcess::GetMemoryRegionInfo returns error.
66 if (err.Success()) {
67 if (!(region.IsReadable() || region.IsWritable())) {
68 is_data_ok = false;
69 response.description = "memory region for address " + addr +
70 " has no read or write permissions";
71 }
72 }
73 } else {
74 is_data_ok = false;
75 response.description =
76 "unable to get byte size for expression: " + args.name;
77 }
78 }
79 } else {
80 is_data_ok = false;
81 response.description = "variable not found: " + args.name;
82 }
83
84 if (is_data_ok) {
85 response.dataId = addr + "/" + size;
86 response.accessTypes = {protocol::eDataBreakpointAccessTypeRead,
87 protocol::eDataBreakpointAccessTypeWrite,
88 protocol::eDataBreakpointAccessTypeReadWrite};
89 response.description = size + " bytes at " + addr + " " + args.name;
90 }
91
92 return response;
93}
94
95} // namespace lldb_dap
96

source code of lldb/tools/lldb-dap/Handler/DataBreakpointInfoRequestHandler.cpp