brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.7 KiB · 3e34e48 Raw
108 lines · cpp
1//===-- WriteMemoryRequestHandler.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 "EventHelper.h"11#include "JSONUtils.h"12#include "Protocol/ProtocolEvents.h"13#include "RequestHandler.h"14#include "lldb/API/SBMemoryRegionInfo.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/Support/Base64.h"17 18using namespace lldb_dap::protocol;19 20namespace lldb_dap {21 22// Writes bytes to memory at the provided location.23//24// Clients should only call this request if the corresponding capability25//  supportsWriteMemoryRequest is true.26llvm::Expected<WriteMemoryResponseBody>27WriteMemoryRequestHandler::Run(const WriteMemoryArguments &args) const {28  const lldb::addr_t address = args.memoryReference + args.offset;29 30  lldb::SBProcess process = dap.target.GetProcess();31  if (!lldb::SBDebugger::StateIsStoppedState(process.GetState()))32    return llvm::make_error<NotStoppedError>();33 34  if (args.data.empty()) {35    return llvm::make_error<DAPError>(36        "Data cannot be empty value. Provide valid data");37  }38 39  // The VSCode IDE or other DAP clients send memory data as a Base64 string.40  // This function decodes it into raw binary before writing it to the target41  // process memory.42  std::vector<char> output;43  auto decode_error = llvm::decodeBase64(args.data, output);44 45  if (decode_error) {46    return llvm::make_error<DAPError>(47        llvm::toString(std::move(decode_error)).c_str());48  }49 50  lldb::SBError write_error;51  uint64_t bytes_written = 0;52 53  // Write the memory.54  if (!output.empty()) {55    lldb::SBProcess process = dap.target.GetProcess();56    // If 'allowPartial' is false or missing, a debug adapter should attempt to57    // verify the region is writable before writing, and fail the response if it58    // is not.59    if (!args.allowPartial) {60      // Start checking from the initial write address.61      lldb::addr_t start_address = address;62      // Compute the end of the write range.63      lldb::addr_t end_address = start_address + output.size() - 1;64 65      while (start_address <= end_address) {66        // Get memory region info for the given address.67        // This provides the region's base, end, and permissions68        // (read/write/executable).69        lldb::SBMemoryRegionInfo region_info;70        lldb::SBError error =71            process.GetMemoryRegionInfo(start_address, region_info);72        // Fail if the region info retrieval fails, is not writable, or the73        // range exceeds the region.74        if (!error.Success() || !region_info.IsWritable()) {75          return llvm::make_error<DAPError>(76              "Memory 0x" + llvm::utohexstr(args.memoryReference) +77              " region is not writable");78        }79        // If the current region covers the full requested range, stop further80        // iterations.81        if (end_address <= region_info.GetRegionEnd()) {82          break;83        }84        // Move to the start of the next memory region.85        start_address = region_info.GetRegionEnd() + 1;86      }87    }88 89    bytes_written =90        process.WriteMemory(address, static_cast<void *>(output.data()),91                            output.size(), write_error);92  }93 94  if (bytes_written == 0) {95    return llvm::make_error<DAPError>(write_error.GetCString());96  }97  WriteMemoryResponseBody response;98  response.bytesWritten = bytes_written;99 100  // Also send invalidated event to signal client that some things101  // (e.g. variables) can be changed.102  SendInvalidatedEvent(dap, {InvalidatedEventBody::eAreaAll});103 104  return response;105}106 107} // namespace lldb_dap108