//===-- SBProcess.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 "lldb/API/SBProcess.h"
#include "lldb/Utility/Instrumentation.h"

#include <cinttypes>

#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"

#include "lldb/Core/AddressRangeListImpl.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"

#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFile.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBMemoryRegionInfoList.h"
#include "lldb/API/SBSaveCoreOptions.h"
#include "lldb/API/SBScriptObject.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBUnixSignals.h"

using namespace lldb;
using namespace lldb_private;

SBProcess::SBProcess() { LLDB_INSTRUMENT_VA(this); }

// SBProcess constructor

SBProcess::SBProcess(const SBProcess &rhs) : m_opaque_wp(rhs.m_opaque_wp) {
  LLDB_INSTRUMENT_VA(this, rhs);
}

SBProcess::SBProcess(const lldb::ProcessSP &process_sp)
    : m_opaque_wp(process_sp) {
  LLDB_INSTRUMENT_VA(this, process_sp);
}

const SBProcess &SBProcess::operator=(const SBProcess &rhs) {
  LLDB_INSTRUMENT_VA(this, rhs);

  if (this != &rhs)
    m_opaque_wp = rhs.m_opaque_wp;
  return *this;
}

// Destructor
SBProcess::~SBProcess() = default;

const char *SBProcess::GetBroadcasterClassName() {
  LLDB_INSTRUMENT();

  return ConstString(Process::GetStaticBroadcasterClass()).AsCString();
}

const char *SBProcess::GetPluginName() {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    return ConstString(process_sp->GetPluginName()).GetCString();
  }
  return "<Unknown>";
}

const char *SBProcess::GetShortPluginName() {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    return ConstString(process_sp->GetPluginName()).GetCString();
  }
  return "<Unknown>";
}

lldb::ProcessSP SBProcess::GetSP() const { return m_opaque_wp.lock(); }

void SBProcess::SetSP(const ProcessSP &process_sp) { m_opaque_wp = process_sp; }

void SBProcess::Clear() {
  LLDB_INSTRUMENT_VA(this);

  m_opaque_wp.reset();
}

bool SBProcess::IsValid() const {
  LLDB_INSTRUMENT_VA(this);
  return this->operator bool();
}
SBProcess::operator bool() const {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(m_opaque_wp.lock());
  return ((bool)process_sp && process_sp->IsValid());
}

bool SBProcess::RemoteLaunch(char const **argv, char const **envp,
                             const char *stdin_path, const char *stdout_path,
                             const char *stderr_path,
                             const char *working_directory,
                             uint32_t launch_flags, bool stop_at_entry,
                             lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, argv, envp, stdin_path, stdout_path, stderr_path,
                     working_directory, launch_flags, stop_at_entry, error);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    if (process_sp->GetState() == eStateConnected) {
      if (stop_at_entry)
        launch_flags |= eLaunchFlagStopAtEntry;
      ProcessLaunchInfo launch_info(FileSpec(stdin_path), FileSpec(stdout_path),
                                    FileSpec(stderr_path),
                                    FileSpec(working_directory), launch_flags);
      Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
      if (exe_module)
        launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
      if (argv)
        launch_info.GetArguments().AppendArguments(argv);
      if (envp)
        launch_info.GetEnvironment() = Environment(envp);
      error.SetError(process_sp->Launch(launch_info));
    } else {
      error = Status::FromErrorString(
          "must be in eStateConnected to call RemoteLaunch");
    }
  } else {
    error = Status::FromErrorString("unable to attach pid");
  }

  return error.Success();
}

bool SBProcess::RemoteAttachToProcessWithID(lldb::pid_t pid,
                                            lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, pid, error);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    if (process_sp->GetState() == eStateConnected) {
      ProcessAttachInfo attach_info;
      attach_info.SetProcessID(pid);
      error.SetError(process_sp->Attach(attach_info));
    } else {
      error = Status::FromErrorString(
          "must be in eStateConnected to call RemoteAttachToProcessWithID");
    }
  } else {
    error = Status::FromErrorString("unable to attach pid");
  }

  return error.Success();
}

uint32_t SBProcess::GetNumThreads() {
  LLDB_INSTRUMENT_VA(this);

  uint32_t num_threads = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;

    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      num_threads = process_sp->GetThreadList().GetSize();
    }
  }

  return num_threads;
}

SBThread SBProcess::GetSelectedThread() const {
  LLDB_INSTRUMENT_VA(this);

  SBThread sb_thread;
  ThreadSP thread_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    thread_sp = process_sp->GetThreadList().GetSelectedThread();
    sb_thread.SetThread(thread_sp);
  }

  return sb_thread;
}

SBThread SBProcess::CreateOSPluginThread(lldb::tid_t tid,
                                         lldb::addr_t context) {
  LLDB_INSTRUMENT_VA(this, tid, context);

  SBThread sb_thread;
  ThreadSP thread_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    thread_sp = process_sp->CreateOSPluginThread(tid, context);
    sb_thread.SetThread(thread_sp);
  }

  return sb_thread;
}

SBTarget SBProcess::GetTarget() const {
  LLDB_INSTRUMENT_VA(this);

  SBTarget sb_target;
  TargetSP target_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    target_sp = process_sp->GetTarget().shared_from_this();
    sb_target.SetSP(target_sp);
  }

  return sb_target;
}

size_t SBProcess::PutSTDIN(const char *src, size_t src_len) {
  LLDB_INSTRUMENT_VA(this, src, src_len);

  size_t ret_val = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Status error;
    ret_val = process_sp->PutSTDIN(src, src_len, error);
  }

  return ret_val;
}

size_t SBProcess::GetSTDOUT(char *dst, size_t dst_len) const {
  LLDB_INSTRUMENT_VA(this, dst, dst_len);

  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Status error;
    bytes_read = process_sp->GetSTDOUT(dst, dst_len, error);
  }

  return bytes_read;
}

size_t SBProcess::GetSTDERR(char *dst, size_t dst_len) const {
  LLDB_INSTRUMENT_VA(this, dst, dst_len);

  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Status error;
    bytes_read = process_sp->GetSTDERR(dst, dst_len, error);
  }

  return bytes_read;
}

size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const {
  LLDB_INSTRUMENT_VA(this, dst, dst_len);

  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Status error;
    bytes_read = process_sp->GetAsyncProfileData(dst, dst_len, error);
  }

  return bytes_read;
}

void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const {
  LLDB_INSTRUMENT_VA(this, event, out);

  return ReportEventState(event, out.m_opaque_sp);
}

void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const {
  LLDB_INSTRUMENT_VA(this, event, out);
  FileSP outfile = std::make_shared<NativeFile>(out, false);
  return ReportEventState(event, outfile);
}

void SBProcess::ReportEventState(const SBEvent &event, FileSP out) const {

  LLDB_INSTRUMENT_VA(this, event, out);

  if (!out || !out->IsValid())
    return;

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    StreamFile stream(out);
    const StateType event_state = SBProcess::GetStateFromEvent(event);
    stream.Printf("Process %" PRIu64 " %s\n", process_sp->GetID(),
                  SBDebugger::StateAsCString(event_state));
  }
}

void SBProcess::AppendEventStateReport(const SBEvent &event,
                                       SBCommandReturnObject &result) {
  LLDB_INSTRUMENT_VA(this, event, result);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    const StateType event_state = SBProcess::GetStateFromEvent(event);
    char message[1024];
    ::snprintf(message, sizeof(message), "Process %" PRIu64 " %s\n",
               process_sp->GetID(), SBDebugger::StateAsCString(event_state));

    result.AppendMessage(message);
  }
}

bool SBProcess::SetSelectedThread(const SBThread &thread) {
  LLDB_INSTRUMENT_VA(this, thread);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    return process_sp->GetThreadList().SetSelectedThreadByID(
        thread.GetThreadID());
  }
  return false;
}

bool SBProcess::SetSelectedThreadByID(lldb::tid_t tid) {
  LLDB_INSTRUMENT_VA(this, tid);

  bool ret_val = false;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    ret_val = process_sp->GetThreadList().SetSelectedThreadByID(tid);
  }

  return ret_val;
}

bool SBProcess::SetSelectedThreadByIndexID(uint32_t index_id) {
  LLDB_INSTRUMENT_VA(this, index_id);

  bool ret_val = false;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    ret_val = process_sp->GetThreadList().SetSelectedThreadByIndexID(index_id);
  }

  return ret_val;
}

SBThread SBProcess::GetThreadAtIndex(size_t index) {
  LLDB_INSTRUMENT_VA(this, index);

  SBThread sb_thread;
  ThreadSP thread_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, false);
      sb_thread.SetThread(thread_sp);
    }
  }

  return sb_thread;
}

uint32_t SBProcess::GetNumQueues() {
  LLDB_INSTRUMENT_VA(this);

  uint32_t num_queues = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      num_queues = process_sp->GetQueueList().GetSize();
    }
  }

  return num_queues;
}

SBQueue SBProcess::GetQueueAtIndex(size_t index) {
  LLDB_INSTRUMENT_VA(this, index);

  SBQueue sb_queue;
  QueueSP queue_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      queue_sp = process_sp->GetQueueList().GetQueueAtIndex(index);
      sb_queue.SetQueue(queue_sp);
    }
  }

  return sb_queue;
}

uint32_t SBProcess::GetStopID(bool include_expression_stops) {
  LLDB_INSTRUMENT_VA(this, include_expression_stops);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    if (include_expression_stops)
      return process_sp->GetStopID();
    else
      return process_sp->GetLastNaturalStopID();
  }
  return 0;
}

SBEvent SBProcess::GetStopEventForStopID(uint32_t stop_id) {
  LLDB_INSTRUMENT_VA(this, stop_id);

  SBEvent sb_event;
  EventSP event_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    event_sp = process_sp->GetStopEventForStopID(stop_id);
    sb_event.reset(event_sp);
  }

  return sb_event;
}

void SBProcess::ForceScriptedState(StateType new_state) {
  LLDB_INSTRUMENT_VA(this, new_state);

  if (ProcessSP process_sp = GetSP()) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    process_sp->ForceScriptedState(new_state);
  }
}

StateType SBProcess::GetState() {
  LLDB_INSTRUMENT_VA(this);

  StateType ret_val = eStateInvalid;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    ret_val = process_sp->GetState();
  }

  return ret_val;
}

int SBProcess::GetExitStatus() {
  LLDB_INSTRUMENT_VA(this);

  int exit_status = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    exit_status = process_sp->GetExitStatus();
  }

  return exit_status;
}

const char *SBProcess::GetExitDescription() {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  if (!process_sp)
    return nullptr;

  std::lock_guard<std::recursive_mutex> guard(
      process_sp->GetTarget().GetAPIMutex());
  return ConstString(process_sp->GetExitDescription()).GetCString();
}

lldb::pid_t SBProcess::GetProcessID() {
  LLDB_INSTRUMENT_VA(this);

  lldb::pid_t ret_val = LLDB_INVALID_PROCESS_ID;
  ProcessSP process_sp(GetSP());
  if (process_sp)
    ret_val = process_sp->GetID();

  return ret_val;
}

uint32_t SBProcess::GetUniqueID() {
  LLDB_INSTRUMENT_VA(this);

  uint32_t ret_val = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp)
    ret_val = process_sp->GetUniqueID();
  return ret_val;
}

ByteOrder SBProcess::GetByteOrder() const {
  LLDB_INSTRUMENT_VA(this);

  ByteOrder byteOrder = eByteOrderInvalid;
  ProcessSP process_sp(GetSP());
  if (process_sp)
    byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder();

  return byteOrder;
}

uint32_t SBProcess::GetAddressByteSize() const {
  LLDB_INSTRUMENT_VA(this);

  uint32_t size = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp)
    size = process_sp->GetTarget().GetArchitecture().GetAddressByteSize();

  return size;
}

SBError SBProcess::Continue() {
  LLDB_INSTRUMENT_VA(this);

  SBError sb_error;
  ProcessSP process_sp(GetSP());

  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());

    if (process_sp->GetTarget().GetDebugger().GetAsyncExecution())
      sb_error.ref() = process_sp->Resume();
    else
      sb_error.ref() = process_sp->ResumeSynchronous(nullptr);
  } else
    sb_error = Status::FromErrorString("SBProcess is invalid");

  return sb_error;
}

SBError SBProcess::ContinueInDirection(RunDirection direction) {
  if (ProcessSP process_sp = GetSP()) {
    if (direction == RunDirection::eRunReverse &&
        !process_sp->SupportsReverseDirection())
      return Status::FromErrorStringWithFormatv(
          "{0} does not support reverse execution of processes",
          GetPluginName());
    process_sp->SetBaseDirection(direction);
  }
  return Continue();
}

SBError SBProcess::Destroy() {
  LLDB_INSTRUMENT_VA(this);

  SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    sb_error.SetError(process_sp->Destroy(false));
  } else
    sb_error = Status::FromErrorString("SBProcess is invalid");

  return sb_error;
}

SBError SBProcess::Stop() {
  LLDB_INSTRUMENT_VA(this);

  SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    sb_error.SetError(process_sp->Halt());
  } else
    sb_error = Status::FromErrorString("SBProcess is invalid");

  return sb_error;
}

SBError SBProcess::Kill() {
  LLDB_INSTRUMENT_VA(this);

  SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    sb_error.SetError(process_sp->Destroy(true));
  } else
    sb_error = Status::FromErrorString("SBProcess is invalid");

  return sb_error;
}

SBError SBProcess::Detach() {
  LLDB_INSTRUMENT_VA(this);

  // FIXME: This should come from a process default.
  bool keep_stopped = false;
  return Detach(keep_stopped);
}

SBError SBProcess::Detach(bool keep_stopped) {
  LLDB_INSTRUMENT_VA(this, keep_stopped);

  SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    sb_error.SetError(process_sp->Detach(keep_stopped));
  } else
    sb_error = Status::FromErrorString("SBProcess is invalid");

  return sb_error;
}

SBError SBProcess::Signal(int signo) {
  LLDB_INSTRUMENT_VA(this, signo);

  SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    sb_error.SetError(process_sp->Signal(signo));
  } else
    sb_error = Status::FromErrorString("SBProcess is invalid");

  return sb_error;
}

SBUnixSignals SBProcess::GetUnixSignals() {
  LLDB_INSTRUMENT_VA(this);

  if (auto process_sp = GetSP())
    return SBUnixSignals{process_sp};

  return SBUnixSignals{};
}

void SBProcess::SendAsyncInterrupt() {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    process_sp->SendAsyncInterrupt();
  }
}

SBThread SBProcess::GetThreadByID(tid_t tid) {
  LLDB_INSTRUMENT_VA(this, tid);

  SBThread sb_thread;
  ThreadSP thread_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    thread_sp = process_sp->GetThreadList().FindThreadByID(tid, can_update);
    sb_thread.SetThread(thread_sp);
  }

  return sb_thread;
}

SBThread SBProcess::GetThreadByIndexID(uint32_t index_id) {
  LLDB_INSTRUMENT_VA(this, index_id);

  SBThread sb_thread;
  ThreadSP thread_sp;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock());
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    thread_sp =
        process_sp->GetThreadList().FindThreadByIndexID(index_id, can_update);
    sb_thread.SetThread(thread_sp);
  }

  return sb_thread;
}

StateType SBProcess::GetStateFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  StateType ret_val = Process::ProcessEventData::GetStateFromEvent(event.get());

  return ret_val;
}

bool SBProcess::GetRestartedFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  bool ret_val = Process::ProcessEventData::GetRestartedFromEvent(event.get());

  return ret_val;
}

size_t SBProcess::GetNumRestartedReasonsFromEvent(const lldb::SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Process::ProcessEventData::GetNumRestartedReasons(event.get());
}

const char *
SBProcess::GetRestartedReasonAtIndexFromEvent(const lldb::SBEvent &event,
                                              size_t idx) {
  LLDB_INSTRUMENT_VA(event, idx);

  return ConstString(Process::ProcessEventData::GetRestartedReasonAtIndex(
                         event.get(), idx))
      .GetCString();
}

SBProcess SBProcess::GetProcessFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  ProcessSP process_sp =
      Process::ProcessEventData::GetProcessFromEvent(event.get());
  if (!process_sp) {
    // StructuredData events also know the process they come from. Try that.
    process_sp = EventDataStructuredData::GetProcessFromEvent(event.get());
  }

  return SBProcess(process_sp);
}

bool SBProcess::GetInterruptedFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Process::ProcessEventData::GetInterruptedFromEvent(event.get());
}

lldb::SBStructuredData
SBProcess::GetStructuredDataFromEvent(const lldb::SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return SBStructuredData(event.GetSP());
}

bool SBProcess::EventIsProcessEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Process::ProcessEventData::GetEventDataFromEvent(event.get()) !=
         nullptr;
}

bool SBProcess::EventIsStructuredDataEvent(const lldb::SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  EventSP event_sp = event.GetSP();
  EventData *event_data = event_sp ? event_sp->GetData() : nullptr;
  return event_data && (event_data->GetFlavor() ==
                        EventDataStructuredData::GetFlavorString());
}

SBBroadcaster SBProcess::GetBroadcaster() const {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());

  SBBroadcaster broadcaster(process_sp.get(), false);

  return broadcaster;
}

const char *SBProcess::GetBroadcasterClass() {
  LLDB_INSTRUMENT();

  return ConstString(Process::GetStaticBroadcasterClass()).AsCString();
}

lldb::SBAddressRangeList SBProcess::FindRangesInMemory(
    const void *buf, uint64_t size, const SBAddressRangeList &ranges,
    uint32_t alignment, uint32_t max_matches, SBError &error) {
  LLDB_INSTRUMENT_VA(this, buf, size, ranges, alignment, max_matches, error);

  lldb::SBAddressRangeList matches;

  ProcessSP process_sp(GetSP());
  if (!process_sp) {
    error = Status::FromErrorString("SBProcess is invalid");
    return matches;
  }
  Process::StopLocker stop_locker;
  if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
    error = Status::FromErrorString("process is running");
    return matches;
  }
  std::lock_guard<std::recursive_mutex> guard(
      process_sp->GetTarget().GetAPIMutex());
  matches.m_opaque_up->ref() = process_sp->FindRangesInMemory(
      reinterpret_cast<const uint8_t *>(buf), size, ranges.ref().ref(),
      alignment, max_matches, error.ref());
  return matches;
}

lldb::addr_t SBProcess::FindInMemory(const void *buf, uint64_t size,
                                     const SBAddressRange &range,
                                     uint32_t alignment, SBError &error) {
  LLDB_INSTRUMENT_VA(this, buf, size, range, alignment, error);

  ProcessSP process_sp(GetSP());

  if (!process_sp) {
    error = Status::FromErrorString("SBProcess is invalid");
    return LLDB_INVALID_ADDRESS;
  }

  Process::StopLocker stop_locker;
  if (!stop_locker.TryLock(&process_sp->GetRunLock())) {
    error = Status::FromErrorString("process is running");
    return LLDB_INVALID_ADDRESS;
  }

  std::lock_guard<std::recursive_mutex> guard(
      process_sp->GetTarget().GetAPIMutex());
  return process_sp->FindInMemory(reinterpret_cast<const uint8_t *>(buf), size,
                                  range.ref(), alignment, error.ref());
}

size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
                             SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error);

  if (!dst) {
    sb_error = Status::FromErrorStringWithFormat(
        "no buffer provided to read %zu bytes into", dst_len);
    return 0;
  }

  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());


  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      bytes_read = process_sp->ReadMemory(addr, dst, dst_len, sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }

  return bytes_read;
}

size_t SBProcess::ReadCStringFromMemory(addr_t addr, void *buf, size_t size,
                                        lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, addr, buf, size, sb_error);

  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      bytes_read = process_sp->ReadCStringFromMemory(addr, (char *)buf, size,
                                                     sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return bytes_read;
}

uint64_t SBProcess::ReadUnsignedFromMemory(addr_t addr, uint32_t byte_size,
                                           lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, addr, byte_size, sb_error);

  uint64_t value = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      value = process_sp->ReadUnsignedIntegerFromMemory(addr, byte_size, 0,
                                                        sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return value;
}

lldb::addr_t SBProcess::ReadPointerFromMemory(addr_t addr,
                                              lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, addr, sb_error);

  lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      ptr = process_sp->ReadPointerFromMemory(addr, sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return ptr;
}

size_t SBProcess::WriteMemory(addr_t addr, const void *src, size_t src_len,
                              SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, addr, src, src_len, sb_error);

  size_t bytes_written = 0;

  ProcessSP process_sp(GetSP());

  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      bytes_written =
          process_sp->WriteMemory(addr, src, src_len, sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  }

  return bytes_written;
}

void SBProcess::GetStatus(SBStream &status) {
  LLDB_INSTRUMENT_VA(this, status);

  ProcessSP process_sp(GetSP());
  if (process_sp)
    process_sp->GetStatus(status.ref());
}

bool SBProcess::GetDescription(SBStream &description) {
  LLDB_INSTRUMENT_VA(this, description);

  Stream &strm = description.ref();

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    char path[PATH_MAX];
    GetTarget().GetExecutable().GetPath(path, sizeof(path));
    Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
    const char *exe_name = nullptr;
    if (exe_module)
      exe_name = exe_module->GetFileSpec().GetFilename().AsCString();

    strm.Printf("SBProcess: pid = %" PRIu64 ", state = %s, threads = %d%s%s",
                process_sp->GetID(), lldb_private::StateAsCString(GetState()),
                GetNumThreads(), exe_name ? ", executable = " : "",
                exe_name ? exe_name : "");
  } else
    strm.PutCString("No value");

  return true;
}

SBStructuredData SBProcess::GetExtendedCrashInformation() {
  LLDB_INSTRUMENT_VA(this);
  SBStructuredData data;
  ProcessSP process_sp(GetSP());
  if (!process_sp)
    return data;

  PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();

  if (!platform_sp)
    return data;

  auto expected_data =
      platform_sp->FetchExtendedCrashInformation(*process_sp.get());

  if (!expected_data)
    return data;

  StructuredData::ObjectSP fetched_data = *expected_data;
  data.m_impl_up->SetObjectSP(fetched_data);
  return data;
}

uint32_t
SBProcess::GetNumSupportedHardwareWatchpoints(lldb::SBError &sb_error) const {
  LLDB_INSTRUMENT_VA(this, sb_error);

  uint32_t num = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    std::optional<uint32_t> actual_num = process_sp->GetWatchpointSlotCount();
    if (actual_num) {
      num = *actual_num;
    } else {
      sb_error =
          Status::FromErrorString("Unable to determine number of watchpoints");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return num;
}

uint32_t SBProcess::LoadImage(lldb::SBFileSpec &sb_remote_image_spec,
                              lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, sb_remote_image_spec, sb_error);

  return LoadImage(SBFileSpec(), sb_remote_image_spec, sb_error);
}

uint32_t SBProcess::LoadImage(const lldb::SBFileSpec &sb_local_image_spec,
                              const lldb::SBFileSpec &sb_remote_image_spec,
                              lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, sb_local_image_spec, sb_remote_image_spec, sb_error);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
      PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
      return platform_sp->LoadImage(process_sp.get(), *sb_local_image_spec,
                                    *sb_remote_image_spec, sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("process is invalid");
  }
  return LLDB_INVALID_IMAGE_TOKEN;
}

uint32_t SBProcess::LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
                                        SBStringList &paths,
                                        lldb::SBFileSpec &loaded_path,
                                        lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, image_spec, paths, loaded_path, error);

  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
      PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
      size_t num_paths = paths.GetSize();
      std::vector<std::string> paths_vec;
      paths_vec.reserve(num_paths);
      for (size_t i = 0; i < num_paths; i++)
        paths_vec.push_back(paths.GetStringAtIndex(i));
      FileSpec loaded_spec;

      uint32_t token = platform_sp->LoadImageUsingPaths(
          process_sp.get(), *image_spec, paths_vec, error.ref(), &loaded_spec);
      if (token != LLDB_INVALID_IMAGE_TOKEN)
        loaded_path = loaded_spec;
      return token;
    } else {
      error = Status::FromErrorString("process is running");
    }
  } else {
    error = Status::FromErrorString("process is invalid");
  }

  return LLDB_INVALID_IMAGE_TOKEN;
}

lldb::SBError SBProcess::UnloadImage(uint32_t image_token) {
  LLDB_INSTRUMENT_VA(this, image_token);

  lldb::SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      PlatformSP platform_sp = process_sp->GetTarget().GetPlatform();
      sb_error.SetError(
          platform_sp->UnloadImage(process_sp.get(), image_token));
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else
    sb_error = Status::FromErrorString("invalid process");
  return sb_error;
}

lldb::SBError SBProcess::SendEventData(const char *event_data) {
  LLDB_INSTRUMENT_VA(this, event_data);

  lldb::SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      sb_error.SetError(process_sp->SendEventData(event_data));
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else
    sb_error = Status::FromErrorString("invalid process");
  return sb_error;
}

uint32_t SBProcess::GetNumExtendedBacktraceTypes() {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  if (process_sp && process_sp->GetSystemRuntime()) {
    SystemRuntime *runtime = process_sp->GetSystemRuntime();
    return runtime->GetExtendedBacktraceTypes().size();
  }
  return 0;
}

const char *SBProcess::GetExtendedBacktraceTypeAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  ProcessSP process_sp(GetSP());
  if (process_sp && process_sp->GetSystemRuntime()) {
    SystemRuntime *runtime = process_sp->GetSystemRuntime();
    const std::vector<ConstString> &names =
        runtime->GetExtendedBacktraceTypes();
    if (idx < names.size()) {
      return names[idx].AsCString();
    }
  }
  return nullptr;
}

SBThreadCollection SBProcess::GetHistoryThreads(addr_t addr) {
  LLDB_INSTRUMENT_VA(this, addr);

  ProcessSP process_sp(GetSP());
  SBThreadCollection threads;
  if (process_sp) {
    threads = SBThreadCollection(process_sp->GetHistoryThreads(addr));
  }
  return threads;
}

bool SBProcess::IsInstrumentationRuntimePresent(
    InstrumentationRuntimeType type) {
  LLDB_INSTRUMENT_VA(this, type);

  ProcessSP process_sp(GetSP());
  if (!process_sp)
    return false;

  std::lock_guard<std::recursive_mutex> guard(
      process_sp->GetTarget().GetAPIMutex());

  InstrumentationRuntimeSP runtime_sp =
      process_sp->GetInstrumentationRuntime(type);

  if (!runtime_sp.get())
    return false;

  return runtime_sp->IsActive();
}

lldb::SBError SBProcess::SaveCore(const char *file_name) {
  LLDB_INSTRUMENT_VA(this, file_name);
  SBSaveCoreOptions options;
  options.SetOutputFile(SBFileSpec(file_name));
  options.SetStyle(SaveCoreStyle::eSaveCoreFull);
  return SaveCore(options);
}

lldb::SBError SBProcess::SaveCore(const char *file_name,
                                  const char *flavor,
                                  SaveCoreStyle core_style) {
  LLDB_INSTRUMENT_VA(this, file_name, flavor, core_style);
  SBSaveCoreOptions options;
  options.SetOutputFile(SBFileSpec(file_name));
  options.SetStyle(core_style);
  SBError error = options.SetPluginName(flavor);
  if (error.Fail())
    return error;
  return SaveCore(options);
}

lldb::SBError SBProcess::SaveCore(SBSaveCoreOptions &options) {

  LLDB_INSTRUMENT_VA(this, options);

  lldb::SBError error;
  ProcessSP process_sp(GetSP());
  if (!process_sp) {
    error = Status::FromErrorString("SBProcess is invalid");
    return error;
  }

  if (!options.GetProcess())
    options.SetProcess(process_sp);

  if (options.GetProcess().GetSP() != process_sp) {
    error = Status::FromErrorString(
        "Save Core Options configured for a different process.");
    return error;
  }

  std::lock_guard<std::recursive_mutex> guard(
      process_sp->GetTarget().GetAPIMutex());

  if (process_sp->GetState() != eStateStopped) {
    error = Status::FromErrorString("the process is not stopped");
    return error;
  }

  error.ref() = PluginManager::SaveCore(options.ref());

  return error;
}

lldb::SBError
SBProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
                               SBMemoryRegionInfo &sb_region_info) {
  LLDB_INSTRUMENT_VA(this, load_addr, sb_region_info);

  lldb::SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());

      sb_error.ref() =
          process_sp->GetMemoryRegionInfo(load_addr, sb_region_info.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return sb_error;
}

lldb::SBMemoryRegionInfoList SBProcess::GetMemoryRegions() {
  LLDB_INSTRUMENT_VA(this);

  lldb::SBMemoryRegionInfoList sb_region_list;

  ProcessSP process_sp(GetSP());
  Process::StopLocker stop_locker;
  if (process_sp && stop_locker.TryLock(&process_sp->GetRunLock())) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());

    process_sp->GetMemoryRegions(sb_region_list.ref());
  }

  return sb_region_list;
}

lldb::SBProcessInfo SBProcess::GetProcessInfo() {
  LLDB_INSTRUMENT_VA(this);

  lldb::SBProcessInfo sb_proc_info;
  ProcessSP process_sp(GetSP());
  ProcessInstanceInfo proc_info;
  if (process_sp && process_sp->GetProcessInfo(proc_info)) {
    sb_proc_info.SetProcessInfo(proc_info);
  }
  return sb_proc_info;
}

lldb::SBFileSpec SBProcess::GetCoreFile() {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  FileSpec core_file;
  if (process_sp) {
    core_file = process_sp->GetCoreFile();
  }
  return SBFileSpec(core_file);
}

addr_t SBProcess::GetAddressMask(AddressMaskType type,
                                 AddressMaskRange addr_range) {
  LLDB_INSTRUMENT_VA(this, type, addr_range);

  if (ProcessSP process_sp = GetSP()) {
    switch (type) {
    case eAddressMaskTypeCode:
      if (addr_range == eAddressMaskRangeHigh)
        return process_sp->GetHighmemCodeAddressMask();
      else
        return process_sp->GetCodeAddressMask();
    case eAddressMaskTypeData:
      if (addr_range == eAddressMaskRangeHigh)
        return process_sp->GetHighmemDataAddressMask();
      else
        return process_sp->GetDataAddressMask();
    case eAddressMaskTypeAny:
      if (addr_range == eAddressMaskRangeHigh)
        return process_sp->GetHighmemDataAddressMask();
      else
        return process_sp->GetDataAddressMask();
    }
  }
  return LLDB_INVALID_ADDRESS_MASK;
}

void SBProcess::SetAddressMask(AddressMaskType type, addr_t mask,
                               AddressMaskRange addr_range) {
  LLDB_INSTRUMENT_VA(this, type, mask, addr_range);

  if (ProcessSP process_sp = GetSP()) {
    switch (type) {
    case eAddressMaskTypeCode:
      if (addr_range == eAddressMaskRangeAll) {
        process_sp->SetCodeAddressMask(mask);
        process_sp->SetHighmemCodeAddressMask(mask);
      } else if (addr_range == eAddressMaskRangeHigh) {
        process_sp->SetHighmemCodeAddressMask(mask);
      } else {
        process_sp->SetCodeAddressMask(mask);
      }
      break;
    case eAddressMaskTypeData:
      if (addr_range == eAddressMaskRangeAll) {
        process_sp->SetDataAddressMask(mask);
        process_sp->SetHighmemDataAddressMask(mask);
      } else if (addr_range == eAddressMaskRangeHigh) {
        process_sp->SetHighmemDataAddressMask(mask);
      } else {
        process_sp->SetDataAddressMask(mask);
      }
      break;
    case eAddressMaskTypeAll:
      if (addr_range == eAddressMaskRangeAll) {
        process_sp->SetCodeAddressMask(mask);
        process_sp->SetDataAddressMask(mask);
        process_sp->SetHighmemCodeAddressMask(mask);
        process_sp->SetHighmemDataAddressMask(mask);
      } else if (addr_range == eAddressMaskRangeHigh) {
        process_sp->SetHighmemCodeAddressMask(mask);
        process_sp->SetHighmemDataAddressMask(mask);
      } else {
        process_sp->SetCodeAddressMask(mask);
        process_sp->SetDataAddressMask(mask);
      }
      break;
    }
  }
}

void SBProcess::SetAddressableBits(AddressMaskType type, uint32_t num_bits,
                                   AddressMaskRange addr_range) {
  LLDB_INSTRUMENT_VA(this, type, num_bits, addr_range);

  SetAddressMask(type, AddressableBits::AddressableBitToMask(num_bits),
                 addr_range);
}

addr_t SBProcess::FixAddress(addr_t addr, AddressMaskType type) {
  LLDB_INSTRUMENT_VA(this, addr, type);

  if (ProcessSP process_sp = GetSP()) {
    if (type == eAddressMaskTypeAny)
      return process_sp->FixAnyAddress(addr);
    else if (type == eAddressMaskTypeData)
      return process_sp->FixDataAddress(addr);
    else if (type == eAddressMaskTypeCode)
      return process_sp->FixCodeAddress(addr);
  }
  return addr;
}

lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions,
                                       lldb::SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, size, permissions, sb_error);

  lldb::addr_t addr = LLDB_INVALID_ADDRESS;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      addr = process_sp->AllocateMemory(size, permissions, sb_error.ref());
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return addr;
}

lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) {
  LLDB_INSTRUMENT_VA(this, ptr);

  lldb::SBError sb_error;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      std::lock_guard<std::recursive_mutex> guard(
          process_sp->GetTarget().GetAPIMutex());
      Status error = process_sp->DeallocateMemory(ptr);
      sb_error.SetError(std::move(error));
    } else {
      sb_error = Status::FromErrorString("process is running");
    }
  } else {
    sb_error = Status::FromErrorString("SBProcess is invalid");
  }
  return sb_error;
}

lldb::SBScriptObject SBProcess::GetScriptedImplementation() {
  LLDB_INSTRUMENT_VA(this);
  ProcessSP process_sp(GetSP());
  return lldb::SBScriptObject((process_sp) ? process_sp->GetImplementation()
                                           : nullptr,
                              eScriptLanguageDefault);
}
