//===-- 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/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.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"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Stream.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/SBTrace.h"
#include "lldb/API/SBTraceOptions.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) {
    Status 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) {
    Status 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) {
    Status 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) {
    Status 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;
}

lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options,
                                    lldb::SBError &error) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  ProcessSP process_sp(GetSP());
  error.Clear();
  SBTrace trace_instance;
  trace_instance.SetSP(process_sp);
  lldb::user_id_t uid = LLDB_INVALID_UID;

  if (!process_sp) {
    error.SetErrorString("invalid process");
  } else {
    uid = process_sp->StartTrace(*(options.m_traceoptions_sp), error.ref());
    trace_instance.SetTraceUID(uid);
    LLDB_LOG(log, "SBProcess::returned uid - {0}", uid);
  }
  return trace_instance;
}

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) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
  ProcessSP process_sp(GetSP());
  if (process_sp) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&process_sp->GetRunLock())) {
      if (log)
        log->Printf("SBProcess(%p)::LoadImage() => calling Platform::LoadImage"
                    "for: %s",
                    static_cast<void *>(process_sp.get()),
                    sb_local_image_spec.GetFilename());

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