brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.7 KiB · 245d92c Raw
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