//===-- SBProcess.cpp -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/API/SBProcess.h"

// C Includes
#include <inttypes.h>

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

#include "lldb/Core/Debugger.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/Stream.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Interpreter/Args.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"

// Project includes

#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBMemoryRegionInfoList.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/SBUnixSignals.h"

using namespace lldb;
using namespace lldb_private;

SBProcess::SBProcess() : m_opaque_wp() {}

//----------------------------------------------------------------------
// SBProcess constructor
//----------------------------------------------------------------------

SBProcess::SBProcess(const SBProcess &rhs) : m_opaque_wp(rhs.m_opaque_wp) {}

SBProcess::SBProcess(const lldb::ProcessSP &process_sp)
    : m_opaque_wp(process_sp) {}

const SBProcess &SBProcess::operator=(const SBProcess &rhs) {
  if (this != &rhs)
    m_opaque_wp = rhs.m_opaque_wp;
  return *this;
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
SBProcess::~SBProcess() {}

const char *SBProcess::GetBroadcasterClassName() {
  return Process::GetStaticBroadcasterClass().AsCString();
}

const char *SBProcess::GetPluginName() {
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    return process_sp->GetPluginName().GetCString();
  }
  return "<Unknown>";
}

const char *SBProcess::GetShortPluginName() {
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    return 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() { m_opaque_wp.reset(); }

bool SBProcess::IsValid() const {
  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) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::RemoteLaunch (argv=%p, envp=%p, stdin=%s, "
                "stdout=%s, stderr=%s, working-dir=%s, launch_flags=0x%x, "
                "stop_at_entry=%i, &error (%p))...",
                static_cast<void *>(m_opaque_wp.lock().get()),
                static_cast<void *>(argv), static_cast<void *>(envp),
                stdin_path ? stdin_path : "NULL",
                stdout_path ? stdout_path : "NULL",
                stderr_path ? stderr_path : "NULL",
                working_directory ? working_directory : "NULL", launch_flags,
                stop_at_entry, static_cast<void *>(error.get()));

  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, false}, FileSpec{stdout_path, false},
          FileSpec{stderr_path, false}, FileSpec{working_directory, false},
          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.GetEnvironmentEntries().SetArguments(envp);
      error.SetError(process_sp->Launch(launch_info));
    } else {
      error.SetErrorString("must be in eStateConnected to call RemoteLaunch");
    }
  } else {
    error.SetErrorString("unable to attach pid");
  }

  if (log) {
    SBStream sstr;
    error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::RemoteLaunch (...) => SBError (%p): %s",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(error.get()), sstr.GetData());
  }

  return error.Success();
}

bool SBProcess::RemoteAttachToProcessWithID(lldb::pid_t pid,
                                            lldb::SBError &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.SetErrorString(
          "must be in eStateConnected to call RemoteAttachToProcessWithID");
    }
  } else {
    error.SetErrorString("unable to attach pid");
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    SBStream sstr;
    error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::RemoteAttachToProcessWithID (%" PRIu64
                ") => SBError (%p): %s",
                static_cast<void *>(process_sp.get()), pid,
                static_cast<void *>(error.get()), sstr.GetData());
  }

  return error.Success();
}

uint32_t SBProcess::GetNumThreads() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  uint32_t num_threads = 0;
  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());
    num_threads = process_sp->GetThreadList().GetSize(can_update);
  }

  if (log)
    log->Printf("SBProcess(%p)::GetNumThreads () => %d",
                static_cast<void *>(process_sp.get()), num_threads);

  return num_threads;
}

SBThread SBProcess::GetSelectedThread() const {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::GetSelectedThread () => SBThread(%p)",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(thread_sp.get()));

  return sb_thread;
}

SBThread SBProcess::CreateOSPluginThread(lldb::tid_t tid,
                                         lldb::addr_t context) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::CreateOSPluginThread (tid=0x%" PRIx64
                ", context=0x%" PRIx64 ") => SBThread(%p)",
                static_cast<void *>(process_sp.get()), tid, context,
                static_cast<void *>(thread_sp.get()));

  return sb_thread;
}

SBTarget SBProcess::GetTarget() const {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::GetTarget () => SBTarget(%p)",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(target_sp.get()));

  return sb_target;
}

size_t SBProcess::PutSTDIN(const char *src, size_t src_len) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::PutSTDIN (src=\"%s\", src_len=%" PRIu64
                ") => %" PRIu64,
                static_cast<void *>(process_sp.get()), src,
                static_cast<uint64_t>(src_len), static_cast<uint64_t>(ret_val));

  return ret_val;
}

size_t SBProcess::GetSTDOUT(char *dst, size_t dst_len) const {
  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Error error;
    bytes_read = process_sp->GetSTDOUT(dst, dst_len, error);
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf(
        "SBProcess(%p)::GetSTDOUT (dst=\"%.*s\", dst_len=%" PRIu64
        ") => %" PRIu64,
        static_cast<void *>(process_sp.get()), static_cast<int>(bytes_read),
        dst, static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read));

  return bytes_read;
}

size_t SBProcess::GetSTDERR(char *dst, size_t dst_len) const {
  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Error error;
    bytes_read = process_sp->GetSTDERR(dst, dst_len, error);
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf(
        "SBProcess(%p)::GetSTDERR (dst=\"%.*s\", dst_len=%" PRIu64
        ") => %" PRIu64,
        static_cast<void *>(process_sp.get()), static_cast<int>(bytes_read),
        dst, static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read));

  return bytes_read;
}

size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const {
  size_t bytes_read = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Error error;
    bytes_read = process_sp->GetAsyncProfileData(dst, dst_len, error);
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf(
        "SBProcess(%p)::GetAsyncProfileData (dst=\"%.*s\", dst_len=%" PRIu64
        ") => %" PRIu64,
        static_cast<void *>(process_sp.get()), static_cast<int>(bytes_read),
        dst, static_cast<uint64_t>(dst_len), static_cast<uint64_t>(bytes_read));

  return bytes_read;
}

void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const {
  if (out == NULL)
    return;

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

    if (message_len > 0)
      ::fwrite(message, 1, message_len, out);
  }
}

void SBProcess::AppendEventStateReport(const SBEvent &event,
                                       SBCommandReturnObject &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) {
  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) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::SetSelectedThreadByID (tid=0x%4.4" PRIx64
                ") => %s",
                static_cast<void *>(process_sp.get()), tid,
                (ret_val ? "true" : "false"));

  return ret_val;
}

bool SBProcess::SetSelectedThreadByIndexID(uint32_t index_id) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::SetSelectedThreadByID (tid=0x%x) => %s",
                static_cast<void *>(process_sp.get()), index_id,
                (ret_val ? "true" : "false"));

  return ret_val;
}

SBThread SBProcess::GetThreadAtIndex(size_t index) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  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().GetThreadAtIndex(index, can_update);
    sb_thread.SetThread(thread_sp);
  }

  if (log)
    log->Printf("SBProcess(%p)::GetThreadAtIndex (index=%d) => SBThread(%p)",
                static_cast<void *>(process_sp.get()),
                static_cast<uint32_t>(index),
                static_cast<void *>(thread_sp.get()));

  return sb_thread;
}

uint32_t SBProcess::GetNumQueues() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::GetNumQueues () => %d",
                static_cast<void *>(process_sp.get()), num_queues);

  return num_queues;
}

SBQueue SBProcess::GetQueueAtIndex(size_t index) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::GetQueueAtIndex (index=%d) => SBQueue(%p)",
                static_cast<void *>(process_sp.get()),
                static_cast<uint32_t>(index),
                static_cast<void *>(queue_sp.get()));

  return sb_queue;
}

uint32_t SBProcess::GetStopID(bool 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) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess(%p)::GetStopEventForStopID (stop_id=%" PRIu32
                ") => SBEvent(%p)",
                static_cast<void *>(process_sp.get()), stop_id,
                static_cast<void *>(event_sp.get()));

  return sb_event;
}

StateType SBProcess::GetState() {

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

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetState () => %s",
                static_cast<void *>(process_sp.get()),
                lldb_private::StateAsCString(ret_val));

  return ret_val;
}

int SBProcess::GetExitStatus() {
  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();
  }
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetExitStatus () => %i (0x%8.8x)",
                static_cast<void *>(process_sp.get()), exit_status,
                exit_status);

  return exit_status;
}

const char *SBProcess::GetExitDescription() {
  const char *exit_desc = NULL;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    exit_desc = process_sp->GetExitDescription();
  }
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetExitDescription () => %s",
                static_cast<void *>(process_sp.get()), exit_desc);
  return exit_desc;
}

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

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetProcessID () => %" PRIu64,
                static_cast<void *>(process_sp.get()), ret_val);

  return ret_val;
}

uint32_t SBProcess::GetUniqueID() {
  uint32_t ret_val = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp)
    ret_val = process_sp->GetUniqueID();
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetUniqueID () => %" PRIu32,
                static_cast<void *>(process_sp.get()), ret_val);
  return ret_val;
}

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

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetByteOrder () => %d",
                static_cast<void *>(process_sp.get()), byteOrder);

  return byteOrder;
}

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

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetAddressByteSize () => %d",
                static_cast<void *>(process_sp.get()), size);

  return size;
}

SBError SBProcess::Continue() {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBError sb_error;
  ProcessSP process_sp(GetSP());

  if (log)
    log->Printf("SBProcess(%p)::Continue ()...",
                static_cast<void *>(process_sp.get()));

  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(NULL);
  } else
    sb_error.SetErrorString("SBProcess is invalid");

  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::Continue () => SBError (%p): %s",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(sb_error.get()), sstr.GetData());
  }

  return sb_error;
}

SBError SBProcess::Destroy() {
  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.SetErrorString("SBProcess is invalid");

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::Destroy () => SBError (%p): %s",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(sb_error.get()), sstr.GetData());
  }

  return sb_error;
}

SBError SBProcess::Stop() {
  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.SetErrorString("SBProcess is invalid");

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::Stop () => SBError (%p): %s",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(sb_error.get()), sstr.GetData());
  }

  return sb_error;
}

SBError SBProcess::Kill() {
  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.SetErrorString("SBProcess is invalid");

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::Kill () => SBError (%p): %s",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(sb_error.get()), sstr.GetData());
  }

  return sb_error;
}

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

SBError SBProcess::Detach(bool 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.SetErrorString("SBProcess is invalid");

  return sb_error;
}

SBError SBProcess::Signal(int 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.SetErrorString("SBProcess is invalid");
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::Signal (signo=%i) => SBError (%p): %s",
                static_cast<void *>(process_sp.get()), signo,
                static_cast<void *>(sb_error.get()), sstr.GetData());
  }
  return sb_error;
}

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

  return {};
}

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

SBThread SBProcess::GetThreadByID(tid_t 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);
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetThreadByID (tid=0x%4.4" PRIx64
                ") => SBThread (%p)",
                static_cast<void *>(process_sp.get()), tid,
                static_cast<void *>(thread_sp.get()));

  return sb_thread;
}

SBThread SBProcess::GetThreadByIndexID(uint32_t 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);
  }

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  if (log)
    log->Printf("SBProcess(%p)::GetThreadByID (tid=0x%x) => SBThread (%p)",
                static_cast<void *>(process_sp.get()), index_id,
                static_cast<void *>(thread_sp.get()));

  return sb_thread;
}

StateType SBProcess::GetStateFromEvent(const SBEvent &event) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess::GetStateFromEvent (event.sp=%p) => %s",
                static_cast<void *>(event.get()),
                lldb_private::StateAsCString(ret_val));

  return ret_val;
}

bool SBProcess::GetRestartedFromEvent(const SBEvent &event) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

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

  if (log)
    log->Printf("SBProcess::%s (event.sp=%p) => %d", __FUNCTION__,
                static_cast<void *>(event.get()), ret_val);

  return ret_val;
}

size_t SBProcess::GetNumRestartedReasonsFromEvent(const lldb::SBEvent &event) {
  return Process::ProcessEventData::GetNumRestartedReasons(event.get());
}

const char *
SBProcess::GetRestartedReasonAtIndexFromEvent(const lldb::SBEvent &event,
                                              size_t idx) {
  return Process::ProcessEventData::GetRestartedReasonAtIndex(event.get(), idx);
}

SBProcess SBProcess::GetProcessFromEvent(const SBEvent &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) {
  return Process::ProcessEventData::GetInterruptedFromEvent(event.get());
}

lldb::SBStructuredData
SBProcess::GetStructuredDataFromEvent(const lldb::SBEvent &event) {
  return SBStructuredData(event.GetSP());
}

bool SBProcess::EventIsProcessEvent(const SBEvent &event) {
  return (event.GetBroadcasterClass() == SBProcess::GetBroadcasterClass()) &&
         !EventIsStructuredDataEvent(event);
}

bool SBProcess::EventIsStructuredDataEvent(const lldb::SBEvent &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 {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  ProcessSP process_sp(GetSP());

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

  if (log)
    log->Printf("SBProcess(%p)::GetBroadcaster () => SBBroadcaster (%p)",
                static_cast<void *>(process_sp.get()),
                static_cast<void *>(broadcaster.get()));

  return broadcaster;
}

const char *SBProcess::GetBroadcasterClass() {
  return Process::GetStaticBroadcasterClass().AsCString();
}

size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len,
                             SBError &sb_error) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  size_t bytes_read = 0;

  ProcessSP process_sp(GetSP());

  if (log)
    log->Printf("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64
                ", dst=%p, dst_len=%" PRIu64 ", SBError (%p))...",
                static_cast<void *>(process_sp.get()), addr,
                static_cast<void *>(dst), static_cast<uint64_t>(dst_len),
                static_cast<void *>(sb_error.get()));

  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 {
      if (log)
        log->Printf("SBProcess(%p)::ReadMemory() => error: process is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }

  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::ReadMemory (addr=0x%" PRIx64
                ", dst=%p, dst_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64,
                static_cast<void *>(process_sp.get()), addr,
                static_cast<void *>(dst), static_cast<uint64_t>(dst_len),
                static_cast<void *>(sb_error.get()), sstr.GetData(),
                static_cast<uint64_t>(bytes_read));
  }

  return bytes_read;
}

size_t SBProcess::ReadCStringFromMemory(addr_t addr, void *buf, size_t size,
                                        lldb::SBError &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 {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBProcess(%p)::ReadCStringFromMemory() => error: process "
                    "is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }
  return bytes_read;
}

uint64_t SBProcess::ReadUnsignedFromMemory(addr_t addr, uint32_t byte_size,
                                           lldb::SBError &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 {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBProcess(%p)::ReadUnsignedFromMemory() => error: process "
                    "is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }
  return value;
}

lldb::addr_t SBProcess::ReadPointerFromMemory(addr_t addr,
                                              lldb::SBError &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 {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBProcess(%p)::ReadPointerFromMemory() => error: process "
                    "is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }
  return ptr;
}

size_t SBProcess::WriteMemory(addr_t addr, const void *src, size_t src_len,
                              SBError &sb_error) {
  size_t bytes_written = 0;

  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  ProcessSP process_sp(GetSP());

  if (log)
    log->Printf("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64
                ", src=%p, src_len=%" PRIu64 ", SBError (%p))...",
                static_cast<void *>(process_sp.get()), addr,
                static_cast<const void *>(src), static_cast<uint64_t>(src_len),
                static_cast<void *>(sb_error.get()));

  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 {
      if (log)
        log->Printf("SBProcess(%p)::WriteMemory() => error: process is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  }

  if (log) {
    SBStream sstr;
    sb_error.GetDescription(sstr);
    log->Printf("SBProcess(%p)::WriteMemory (addr=0x%" PRIx64
                ", src=%p, src_len=%" PRIu64 ", SBError (%p): %s) => %" PRIu64,
                static_cast<void *>(process_sp.get()), addr,
                static_cast<const void *>(src), static_cast<uint64_t>(src_len),
                static_cast<void *>(sb_error.get()), sstr.GetData(),
                static_cast<uint64_t>(bytes_written));
  }

  return bytes_written;
}

bool SBProcess::GetDescription(SBStream &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 = NULL;
    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;
}

uint32_t
SBProcess::GetNumSupportedHardwareWatchpoints(lldb::SBError &sb_error) const {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  uint32_t num = 0;
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    std::lock_guard<std::recursive_mutex> guard(
        process_sp->GetTarget().GetAPIMutex());
    sb_error.SetError(process_sp->GetWatchpointSupportInfo(num));
    if (log)
      log->Printf("SBProcess(%p)::GetNumSupportedHardwareWatchpoints () => %u",
                  static_cast<void *>(process_sp.get()), num);
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }
  return num;
}

uint32_t SBProcess::LoadImage(lldb::SBFileSpec &sb_remote_image_spec,
                              lldb::SBError &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) {
  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 {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBProcess(%p)::LoadImage() => error: process is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  }
  return LLDB_INVALID_IMAGE_TOKEN;
}

lldb::SBError SBProcess::UnloadImage(uint32_t 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 {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBProcess(%p)::UnloadImage() => error: process is running",
                    static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else
    sb_error.SetErrorString("invalid process");
  return sb_error;
}

lldb::SBError SBProcess::SendEventData(const char *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 {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf(
            "SBProcess(%p)::SendEventData() => error: process is running",
            static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else
    sb_error.SetErrorString("invalid process");
  return sb_error;
}

uint32_t SBProcess::GetNumExtendedBacktraceTypes() {
  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) {
  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();
    } else {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf("SBProcess(%p)::GetExtendedBacktraceTypeAtIndex() => "
                    "error: requested extended backtrace name out of bounds",
                    static_cast<void *>(process_sp.get()));
    }
  }
  return NULL;
}

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

bool SBProcess::IsInstrumentationRuntimePresent(
    InstrumentationRuntimeType type) {
  ProcessSP process_sp(GetSP());
  if (!process_sp)
    return false;

  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::SBError error;
  ProcessSP process_sp(GetSP());
  if (!process_sp) {
    error.SetErrorString("SBProcess is invalid");
    return error;
  }

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

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

  FileSpec core_file(file_name, false);
  error.ref() = PluginManager::SaveCore(process_sp, core_file);
  return error;
}

lldb::SBError
SBProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
                               SBMemoryRegionInfo &sb_region_info) {
  lldb::SBError sb_error;
  ProcessSP process_sp(GetSP());
  MemoryRegionInfoSP region_info_sp =
      std::make_shared<lldb_private::MemoryRegionInfo>();
  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, *region_info_sp);
      if (sb_error.Success()) {
        sb_region_info.ref() = *region_info_sp;
      }
    } else {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf(
            "SBProcess(%p)::GetMemoryRegionInfo() => error: process is running",
            static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }
  return sb_error;
}

lldb::SBMemoryRegionInfoList SBProcess::GetMemoryRegions() {
  lldb::SBError sb_error;
  lldb::SBMemoryRegionInfoList sb_region_list;
  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());
      std::vector<MemoryRegionInfoSP> region_list;
      sb_error.ref() = process_sp->GetMemoryRegions(region_list);
      if (sb_error.Success()) {
        std::vector<MemoryRegionInfoSP>::iterator end = region_list.end();
        for (std::vector<MemoryRegionInfoSP>::iterator it = region_list.begin();
             it != end; it++) {
          SBMemoryRegionInfo sb_region_info(it->get());
          sb_region_list.Append(sb_region_info);
        }
      }
    } else {
      Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
      if (log)
        log->Printf(
            "SBProcess(%p)::GetMemoryRegionInfo() => error: process is running",
            static_cast<void *>(process_sp.get()));
      sb_error.SetErrorString("process is running");
    }
  } else {
    sb_error.SetErrorString("SBProcess is invalid");
  }
  return sb_region_list;
}
