//===-- 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/Host/File.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/AddressSpace.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/SBAddress.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(nullptr);
}

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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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, File::eOpenOptionWriteOnly, 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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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()) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    process_sp->ForceScriptedState(new_state);
  }
}

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

  StateType ret_val = eStateInvalid;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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;

  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);
  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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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());
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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());
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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(nullptr);
}

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;
  }
  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);
  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;
  }

  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);
  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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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::ReadMemory(SBProcessAddress process_addr, void *dst,
                             size_t dst_len, SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, process_addr, dst, dst_len, sb_error);

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

  ProcessSP process_sp(GetSP());
  if (!process_sp) {
    sb_error = Status::FromErrorString("SBProcess is invalid");
    return 0;
  }

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

  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);
  return process_sp->ReadMemory(process_addr.ref(), dst, dst_len,
                                sb_error.ref());
}

lldb::addr_space_t SBProcess::GetAddressSpaceID(const char *name,
                                                SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, name, sb_error);

  ProcessSP process_sp(GetSP());
  if (!process_sp) {
    sb_error = Status::FromErrorString("SBProcess is invalid");
    return LLDB_INVALID_ADDRESS_SPACE_ID;
  }

  if (!name || !name[0]) {
    sb_error = Status::FromErrorString("an address space name is required");
    return LLDB_INVALID_ADDRESS_SPACE_ID;
  }

  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);
  llvm::Expected<AddressSpaceInfo> info = process_sp->GetAddressSpaceInfo(name);
  if (!info) {
    sb_error = Status::FromError(info.takeError());
    return LLDB_INVALID_ADDRESS_SPACE_ID;
  }
  sb_error.Clear();
  return info->space_id;
}

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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      if (llvm::Expected<lldb::addr_t> ptr_or_err =
              process_sp->ReadPointerFromMemory(addr))
        ptr = *ptr_or_err;
      else
        sb_error = Status::FromError(ptr_or_err.takeError());
    } 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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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 = ConstString(exe_module->GetFileSpec().GetFilename())
                     .AsCString(nullptr);

    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) {
    LLDB_LOG_ERROR(GetLog(LLDBLog::API), expected_data.takeError(),
                   "FetchExtendedCrashInformation failed: {0}");
    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) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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(nullptr);
    }
  }
  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;

  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);

  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;
  }

  TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);

  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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);

      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())) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    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);
}

bool SBProcess::IsLiveDebugSession() const {
  LLDB_INSTRUMENT_VA(this);

  ProcessSP process_sp(GetSP());
  if (!process_sp)
    return false;
  return process_sp->IsLiveDebugSession();
}

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()) {
    TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    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;
    }
    process_sp->AddressMaskChangedCallback();
  }
}

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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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())) {
      TargetAPIMutex api_lock = process_sp->GetTarget().GetAPIMutex();
      std::lock_guard<TargetAPIMutex> guard(api_lock);
      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);
}
