121 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "DAP.h"10#include "DAPError.h"11#include "EventHelper.h"12#include "Protocol/ProtocolTypes.h"13#include "RequestHandler.h"14#include "lldb/API/SBAddress.h"15#include "lldb/API/SBMemoryRegionInfo.h"16#include "llvm/ADT/StringExtras.h"17#include <optional>18 19namespace lldb_dap {20 21static bool IsRW(DAP &dap, lldb::addr_t load_addr) {22 if (!lldb::SBAddress(load_addr, dap.target).IsValid())23 return false;24 lldb::SBMemoryRegionInfo region;25 lldb::SBError err =26 dap.target.GetProcess().GetMemoryRegionInfo(load_addr, region);27 // Only lldb-server supports "qMemoryRegionInfo". So, don't fail this28 // request if SBProcess::GetMemoryRegionInfo returns error.29 if (err.Success()) {30 if (!(region.IsReadable() || region.IsWritable())) {31 return false;32 }33 }34 return true;35}36 37/// Obtains information on a possible data breakpoint that could be set on an38/// expression or variable. Clients should only call this request if the39/// corresponding capability supportsDataBreakpoints is true.40llvm::Expected<protocol::DataBreakpointInfoResponseBody>41DataBreakpointInfoRequestHandler::Run(42 const protocol::DataBreakpointInfoArguments &args) const {43 protocol::DataBreakpointInfoResponseBody response;44 lldb::SBValue variable = dap.variables.FindVariable(45 args.variablesReference.value_or(0), args.name);46 std::string addr, size;47 48 bool is_data_ok = true;49 if (variable.IsValid()) {50 lldb::addr_t load_addr = variable.GetLoadAddress();51 size_t byte_size = variable.GetByteSize();52 if (load_addr == LLDB_INVALID_ADDRESS) {53 is_data_ok = false;54 response.description = "does not exist in memory, its location is " +55 std::string(variable.GetLocation());56 } else if (byte_size == 0) {57 is_data_ok = false;58 response.description = "variable size is 0";59 } else {60 addr = llvm::utohexstr(load_addr);61 size = llvm::utostr(byte_size);62 }63 } else if (lldb::SBFrame frame = dap.GetLLDBFrame(args.frameId);64 args.variablesReference.value_or(0) == 0 && frame.IsValid()) {65 lldb::SBValue value = frame.EvaluateExpression(args.name.c_str());66 if (value.GetError().Fail()) {67 lldb::SBError error = value.GetError();68 const char *error_cstr = error.GetCString();69 is_data_ok = false;70 response.description = error_cstr && error_cstr[0]71 ? std::string(error_cstr)72 : "evaluation failed";73 } else {74 uint64_t load_addr = value.GetValueAsUnsigned();75 lldb::SBData data = value.GetPointeeData();76 if (data.IsValid()) {77 size = llvm::utostr(data.GetByteSize());78 addr = llvm::utohexstr(load_addr);79 if (!IsRW(dap, load_addr)) {80 is_data_ok = false;81 response.description = "memory region for address " + addr +82 " has no read or write permissions";83 }84 } else {85 is_data_ok = false;86 response.description =87 "unable to get byte size for expression: " + args.name;88 }89 }90 } else if (args.asAddress) {91 size = llvm::utostr(args.bytes.value_or(dap.target.GetAddressByteSize()));92 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;93 if (llvm::StringRef(args.name).getAsInteger<lldb::addr_t>(0, load_addr))94 return llvm::make_error<DAPError>(args.name + " is not a valid address",95 llvm::inconvertibleErrorCode(), false);96 addr = llvm::utohexstr(load_addr);97 if (!IsRW(dap, load_addr))98 return llvm::make_error<DAPError>("memory region for address " + addr +99 " has no read or write permissions",100 llvm::inconvertibleErrorCode(), false);101 } else {102 is_data_ok = false;103 response.description = "variable not found: " + args.name;104 }105 106 if (is_data_ok) {107 response.dataId = addr + "/" + size;108 response.accessTypes = {protocol::eDataBreakpointAccessTypeRead,109 protocol::eDataBreakpointAccessTypeWrite,110 protocol::eDataBreakpointAccessTypeReadWrite};111 if (args.asAddress)112 response.description = size + " bytes at " + addr;113 else114 response.description = size + " bytes at " + addr + " " + args.name;115 }116 117 return response;118}119 120} // namespace lldb_dap121