//===-- SBTarget.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/SBTarget.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEnvironment.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBExpressionOptions.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBListener.h"
#include "lldb/API/SBModule.h"
#include "lldb/API/SBModuleSpec.h"
#include "lldb/API/SBMutex.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBStringList.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBSymbolContextList.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBTrace.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/ScriptedBreakpointOverrideResolver.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressResolver.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h"
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/SyntheticFrameProvider.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Instrumentation.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/ProcessInfo.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/ScriptedMetadata.h"
#include "lldb/ValueObject/ValueObjectConstResult.h"
#include "lldb/ValueObject/ValueObjectList.h"
#include "lldb/ValueObject/ValueObjectVariable.h"
#include "lldb/lldb-public.h"

#include "Commands/CommandObjectBreakpoint.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"

using namespace lldb;
using namespace lldb_private;

#define DEFAULT_DISASM_BYTE_SIZE 32

static Status AttachToProcess(ProcessAttachInfo &attach_info, Target &target) {
  TargetAPIMutex api_lock = target.GetAPIMutex();
  std::lock_guard<TargetAPIMutex> guard(api_lock);

  auto process_sp = target.GetProcessSP();
  if (process_sp) {
    const auto state = process_sp->GetState();
    if (process_sp->IsAlive() && state == eStateConnected) {
      // If we are already connected, then we have already specified the
      // listener, so if a valid listener is supplied, we need to error out to
      // let the client know.
      if (attach_info.GetListener())
        return Status::FromErrorString(
            "process is connected and already has a listener, pass "
            "empty listener");
    }
  }

  return target.Attach(attach_info, nullptr);
}

// SBTarget constructor
SBTarget::SBTarget() { LLDB_INSTRUMENT_VA(this); }

SBTarget::SBTarget(const SBTarget &rhs) : m_opaque_sp(rhs.m_opaque_sp) {
  LLDB_INSTRUMENT_VA(this, rhs);
}

SBTarget::SBTarget(const TargetSP &target_sp) : m_opaque_sp(target_sp) {
  LLDB_INSTRUMENT_VA(this, target_sp);
}

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

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

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

bool SBTarget::EventIsTargetEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Target::TargetEventData::GetEventDataFromEvent(event.get()) != nullptr;
}

SBTarget SBTarget::GetTargetFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Target::TargetEventData::GetTargetFromEvent(event.get());
}

SBTarget SBTarget::GetCreatedTargetFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  return Target::TargetEventData::GetCreatedTargetFromEvent(event.get());
}

uint32_t SBTarget::GetNumModulesFromEvent(const SBEvent &event) {
  LLDB_INSTRUMENT_VA(event);

  const ModuleList module_list =
      Target::TargetEventData::GetModuleListFromEvent(event.get());
  return module_list.GetSize();
}

SBModule SBTarget::GetModuleAtIndexFromEvent(const uint32_t idx,
                                             const SBEvent &event) {
  LLDB_INSTRUMENT_VA(idx, event);

  const ModuleList module_list =
      Target::TargetEventData::GetModuleListFromEvent(event.get());
  return SBModule(module_list.GetModuleAtIndex(idx));
}

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

  return ConstString(Target::GetStaticBroadcasterClass()).AsCString(nullptr);
}

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

  return m_opaque_sp.get() != nullptr && m_opaque_sp->IsValid();
}

SBProcess SBTarget::GetProcess() {
  LLDB_INSTRUMENT_VA(this);

  SBProcess sb_process;
  ProcessSP process_sp;
  if (TargetSP target_sp = GetSP()) {
    process_sp = target_sp->GetProcessSP();
    sb_process.SetSP(process_sp);
  }

  return sb_process;
}

SBPlatform SBTarget::GetPlatform() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    SBPlatform platform;
    platform.m_opaque_sp = target_sp->GetPlatform();
    return platform;
  }
  return SBPlatform();
}

SBDebugger SBTarget::GetDebugger() const {
  LLDB_INSTRUMENT_VA(this);

  SBDebugger debugger;
  if (TargetSP target_sp = GetSP())
    debugger.reset(target_sp->GetDebugger().shared_from_this());
  return debugger;
}

SBStructuredData SBTarget::GetStatistics() {
  LLDB_INSTRUMENT_VA(this);
  SBStatisticsOptions options;
  return GetStatistics(options);
}

SBStructuredData SBTarget::GetStatistics(SBStatisticsOptions options) {
  LLDB_INSTRUMENT_VA(this);

  SBStructuredData data;
  if (TargetSP target_sp = GetSP()) {
    std::string json_str =
        llvm::formatv("{0:2}", DebuggerStats::ReportStatistics(
                                   target_sp->GetDebugger(), target_sp.get(),
                                   options.ref()))
            .str();
    data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str));
    return data;
  }
  return data;
}

void SBTarget::ResetStatistics() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    DebuggerStats::ResetStatistics(target_sp->GetDebugger(), target_sp.get());
}

void SBTarget::SetCollectingStats(bool v) {
  LLDB_INSTRUMENT_VA(this, v);

  if (TargetSP target_sp = GetSP())
    DebuggerStats::SetCollectingStats(v);
}

bool SBTarget::GetCollectingStats() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return DebuggerStats::GetCollectingStats();
  return false;
}

SBProcess SBTarget::LoadCore(const char *core_file) {
  LLDB_INSTRUMENT_VA(this, core_file);

  lldb::SBError error; // Ignored
  return LoadCore(core_file, error);
}

SBProcess SBTarget::LoadCore(const char *core_file, lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, core_file, error);

  SBProcess sb_process;
  if (TargetSP target_sp = GetSP()) {
    FileSpec filespec(core_file);
    FileSystem::Instance().Resolve(filespec);
    ProcessSP process_sp(target_sp->CreateProcess(
        target_sp->GetDebugger().GetListener(), "", &filespec, false));
    if (process_sp) {
      ElapsedTime load_core_time(target_sp->GetStatistics().GetLoadCoreTime());
      error.SetError(process_sp->LoadCore());
      if (error.Success())
        sb_process.SetSP(process_sp);
    } else {
      error.SetErrorString("Failed to create the process");
    }
  } else {
    error.SetErrorString("SBTarget is invalid");
  }
  return sb_process;
}

SBProcess SBTarget::LaunchSimple(char const **argv, char const **envp,
                                 const char *working_directory) {
  LLDB_INSTRUMENT_VA(this, argv, envp, working_directory);

  TargetSP target_sp = GetSP();
  if (!target_sp)
    return SBProcess();

  SBLaunchInfo launch_info = GetLaunchInfo();

  if (Module *exe_module = target_sp->GetExecutableModulePointer())
    launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(),
                                  /*add_as_first_arg*/ true);
  if (argv)
    launch_info.SetArguments(argv, /*append*/ true);
  if (envp)
    launch_info.SetEnvironmentEntries(envp, /*append*/ false);
  if (working_directory)
    launch_info.SetWorkingDirectory(working_directory);

  SBError error;
  return Launch(launch_info, error);
}

SBError SBTarget::Install() {
  LLDB_INSTRUMENT_VA(this);

  SBError sb_error;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    sb_error.ref() = target_sp->Install(nullptr);
  }
  return sb_error;
}

SBProcess SBTarget::Launch(SBListener &listener, 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, // See LaunchFlags
                           bool stop_at_entry, lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, listener, argv, envp, stdin_path, stdout_path,
                     stderr_path, working_directory, launch_flags,
                     stop_at_entry, error);

  SBProcess sb_process;
  ProcessSP process_sp;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    if (stop_at_entry)
      launch_flags |= eLaunchFlagStopAtEntry;

    if (getenv("LLDB_LAUNCH_FLAG_DISABLE_ASLR"))
      launch_flags |= eLaunchFlagDisableASLR;

    if (getenv("LLDB_LAUNCH_FLAG_USE_PIPES"))
      launch_flags |= eLaunchFlagUsePipes;

    StateType state = eStateInvalid;
    process_sp = target_sp->GetProcessSP();
    if (process_sp) {
      state = process_sp->GetState();

      if (process_sp->IsAlive() && state != eStateConnected) {
        if (state == eStateAttaching)
          error.SetErrorString("process attach is in progress");
        else
          error.SetErrorString("a process is already being debugged");
        return sb_process;
      }
    }

    if (state == eStateConnected) {
      // If we are already connected, then we have already specified the
      // listener, so if a valid listener is supplied, we need to error out to
      // let the client know.
      if (listener.IsValid()) {
        error.SetErrorString("process is connected and already has a listener, "
                             "pass empty listener");
        return sb_process;
      }
    }

    if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO"))
      launch_flags |= eLaunchFlagDisableSTDIO;

    ProcessLaunchInfo launch_info(FileSpec(stdin_path), FileSpec(stdout_path),
                                  FileSpec(stderr_path),
                                  FileSpec(working_directory), launch_flags);

    Module *exe_module = target_sp->GetExecutableModulePointer();
    if (exe_module)
      launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
    if (argv) {
      launch_info.GetArguments().AppendArguments(argv);
    } else {
      auto default_launch_info = target_sp->GetProcessLaunchInfo();
      launch_info.GetArguments().AppendArguments(
          default_launch_info.GetArguments());
    }
    if (envp) {
      launch_info.GetEnvironment() = Environment(envp);
    } else {
      auto default_launch_info = target_sp->GetProcessLaunchInfo();
      launch_info.GetEnvironment() = default_launch_info.GetEnvironment();
    }

    if (listener.IsValid())
      launch_info.SetListener(listener.GetSP());

    error.SetError(target_sp->Launch(launch_info, nullptr));

    sb_process.SetSP(target_sp->GetProcessSP());
  } else {
    error.SetErrorString("SBTarget is invalid");
  }

  return sb_process;
}

SBProcess SBTarget::Launch(SBLaunchInfo &sb_launch_info, SBError &error) {
  LLDB_INSTRUMENT_VA(this, sb_launch_info, error);

  SBProcess sb_process;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    StateType state = eStateInvalid;
    {
      ProcessSP process_sp = target_sp->GetProcessSP();
      if (process_sp) {
        state = process_sp->GetState();

        if (process_sp->IsAlive() && state != eStateConnected) {
          if (state == eStateAttaching)
            error.SetErrorString("process attach is in progress");
          else
            error.SetErrorString("a process is already being debugged");
          return sb_process;
        }
      }
    }

    lldb_private::ProcessLaunchInfo launch_info = sb_launch_info.ref();

    if (!launch_info.GetExecutableFile()) {
      Module *exe_module = target_sp->GetExecutableModulePointer();
      if (exe_module)
        launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
    }

    const ArchSpec &arch_spec = target_sp->GetArchitecture();
    if (arch_spec.IsValid())
      launch_info.GetArchitecture() = arch_spec;

    error.SetError(target_sp->Launch(launch_info, nullptr));
    sb_launch_info.set_ref(launch_info);
    sb_process.SetSP(target_sp->GetProcessSP());
  } else {
    error.SetErrorString("SBTarget is invalid");
  }

  return sb_process;
}

lldb::SBProcess SBTarget::Attach(SBAttachInfo &sb_attach_info, SBError &error) {
  LLDB_INSTRUMENT_VA(this, sb_attach_info, error);

  SBProcess sb_process;
  if (TargetSP target_sp = GetSP()) {
    ProcessAttachInfo &attach_info = sb_attach_info.ref();
    if (attach_info.ProcessIDIsValid() && !attach_info.UserIDIsValid() &&
        !attach_info.IsScriptedProcess()) {
      PlatformSP platform_sp = target_sp->GetPlatform();
      // See if we can pre-verify if a process exists or not
      if (platform_sp && platform_sp->IsConnected()) {
        lldb::pid_t attach_pid = attach_info.GetProcessID();
        ProcessInstanceInfo instance_info;
        if (platform_sp->GetProcessInfo(attach_pid, instance_info)) {
          attach_info.SetUserID(instance_info.GetEffectiveUserID());
        } else {
          error.ref() = Status::FromErrorStringWithFormat(
              "no process found with process ID %" PRIu64, attach_pid);
          return sb_process;
        }
      }
    }
    error.SetError(AttachToProcess(attach_info, *target_sp));
    if (error.Success())
      sb_process.SetSP(target_sp->GetProcessSP());
  } else {
    error.SetErrorString("SBTarget is invalid");
  }

  return sb_process;
}

lldb::SBProcess SBTarget::AttachToProcessWithID(
    SBListener &listener,
    lldb::pid_t pid, // The process ID to attach to
    SBError &error   // An error explaining what went wrong if attach fails
) {
  LLDB_INSTRUMENT_VA(this, listener, pid, error);

  SBProcess sb_process;
  if (TargetSP target_sp = GetSP()) {
    ProcessAttachInfo attach_info;
    attach_info.SetProcessID(pid);
    if (listener.IsValid())
      attach_info.SetListener(listener.GetSP());

    ProcessInstanceInfo instance_info;
    if (target_sp->GetPlatform()->GetProcessInfo(pid, instance_info))
      attach_info.SetUserID(instance_info.GetEffectiveUserID());

    error.SetError(AttachToProcess(attach_info, *target_sp));
    if (error.Success())
      sb_process.SetSP(target_sp->GetProcessSP());
  } else
    error.SetErrorString("SBTarget is invalid");

  return sb_process;
}

lldb::SBProcess SBTarget::AttachToProcessWithName(
    SBListener &listener,
    const char *name, // basename of process to attach to
    bool wait_for, // if true wait for a new instance of "name" to be launched
    SBError &error // An error explaining what went wrong if attach fails
) {
  LLDB_INSTRUMENT_VA(this, listener, name, wait_for, error);

  SBProcess sb_process;

  if (!name) {
    error.SetErrorString("invalid name");
    return sb_process;
  }

  if (TargetSP target_sp = GetSP()) {
    ProcessAttachInfo attach_info;
    attach_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
    attach_info.SetWaitForLaunch(wait_for);
    if (listener.IsValid())
      attach_info.SetListener(listener.GetSP());

    error.SetError(AttachToProcess(attach_info, *target_sp));
    if (error.Success())
      sb_process.SetSP(target_sp->GetProcessSP());
  } else {
    error.SetErrorString("SBTarget is invalid");
  }

  return sb_process;
}

lldb::SBProcess SBTarget::ConnectRemote(SBListener &listener, const char *url,
                                        const char *plugin_name,
                                        SBError &error) {
  LLDB_INSTRUMENT_VA(this, listener, url, plugin_name, error);

  SBProcess sb_process;
  ProcessSP process_sp;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    if (listener.IsValid())
      process_sp =
          target_sp->CreateProcess(listener.m_opaque_sp, plugin_name, nullptr,
                                   true);
    else
      process_sp = target_sp->CreateProcess(
          target_sp->GetDebugger().GetListener(), plugin_name, nullptr, true);

    if (process_sp) {
      sb_process.SetSP(process_sp);
      error.SetError(process_sp->ConnectRemote(url));
    } else {
      error.SetErrorString("unable to create lldb_private::Process");
    }
  } else {
    error.SetErrorString("SBTarget is invalid");
  }

  return sb_process;
}

SBFileSpec SBTarget::GetExecutable() {
  LLDB_INSTRUMENT_VA(this);

  SBFileSpec exe_file_spec;
  if (TargetSP target_sp = GetSP()) {
    Module *exe_module = target_sp->GetExecutableModulePointer();
    if (exe_module)
      exe_file_spec.SetFileSpec(exe_module->GetFileSpec());
  }

  return exe_file_spec;
}

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

  return m_opaque_sp.get() == rhs.m_opaque_sp.get();
}

bool SBTarget::operator!=(const SBTarget &rhs) const {
  LLDB_INSTRUMENT_VA(this, rhs);

  return m_opaque_sp.get() != rhs.m_opaque_sp.get();
}

lldb::TargetSP SBTarget::GetSP() const { return m_opaque_sp; }

void SBTarget::SetSP(const lldb::TargetSP &target_sp) {
  m_opaque_sp = target_sp;
}

lldb::SBAddress SBTarget::ResolveLoadAddress(lldb::addr_t vm_addr) {
  LLDB_INSTRUMENT_VA(this, vm_addr);

  lldb::SBAddress sb_addr;
  Address &addr = sb_addr.ref();
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    if (target_sp->ResolveLoadAddress(vm_addr, addr))
      return sb_addr;
  }

  // We have a load address that isn't in a section, just return an address
  // with the offset filled in (the address) and the section set to NULL
  addr.SetRawAddress(vm_addr);
  return sb_addr;
}

lldb::SBAddress SBTarget::ResolveFileAddress(lldb::addr_t file_addr) {
  LLDB_INSTRUMENT_VA(this, file_addr);

  lldb::SBAddress sb_addr;
  Address &addr = sb_addr.ref();
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    if (target_sp->ResolveFileAddress(file_addr, addr))
      return sb_addr;
  }

  addr.SetRawAddress(file_addr);
  return sb_addr;
}

lldb::SBAddress SBTarget::ResolvePastLoadAddress(uint32_t stop_id,
                                                 lldb::addr_t vm_addr) {
  LLDB_INSTRUMENT_VA(this, stop_id, vm_addr);

  lldb::SBAddress sb_addr;
  Address &addr = sb_addr.ref();
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    if (target_sp->ResolveLoadAddress(vm_addr, addr))
      return sb_addr;
  }

  // We have a load address that isn't in a section, just return an address
  // with the offset filled in (the address) and the section set to NULL
  addr.SetRawAddress(vm_addr);
  return sb_addr;
}

SBSymbolContext
SBTarget::ResolveSymbolContextForAddress(const SBAddress &addr,
                                         uint32_t resolve_scope) {
  LLDB_INSTRUMENT_VA(this, addr, resolve_scope);

  SBSymbolContext sb_sc;
  SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
  if (addr.IsValid()) {
    if (TargetSP target_sp = GetSP()) {
      lldb_private::SymbolContext &sc = sb_sc.ref();
      sc.target_sp = target_sp;
      target_sp->GetImages().ResolveSymbolContextForAddress(addr.ref(), scope,
                                                            sc);
    }
  }
  return sb_sc;
}

size_t SBTarget::ReadMemory(const SBAddress addr, void *buf, size_t size,
                            lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, addr, buf, size, error);

  size_t bytes_read = 0;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    bytes_read =
        target_sp->ReadMemory(addr.ref(), buf, size, error.ref(), true);
  } else {
    error.SetErrorString("invalid target");
  }

  return bytes_read;
}

uint64_t SBTarget::AddBreakpointOverride(const char *class_name,
                                         const char *description,
                                         uint64_t type_mask,
                                         SBStructuredData &args_data,
                                         SBError &error) {
  if (!class_name || class_name[0] == '\0') {
    error.SetErrorString("empty class name");
    return LLDB_INVALID_INDEX64;
  }

  if (TargetSP target_sp = GetSP()) {
    StructuredDataImpl impl;
    args_data.CopyImpl(impl);
    StructuredData::ObjectSP object_sp = impl.GetObjectSP();
    StructuredData::DictionarySP args_dict(
        new StructuredData::Dictionary(object_sp));
    if (!args_dict->IsValid()) {
      error.SetErrorString("args data is not a dictionary");
      return LLDB_INVALID_INDEX64;
    }

    llvm::Expected<lldb::user_id_t> id_or_err =
        target_sp->AddBreakpointResolverOverride(
            class_name, type_mask, args_dict,
            description ? description : "<No Description>");
    if (id_or_err)
      return *id_or_err;
    error.SetErrorString(llvm::toString(id_or_err.takeError()).c_str());
    return LLDB_INVALID_INDEX64;

  } else {
    error.SetErrorString("invalid SBTarget.");
    return LLDB_INVALID_INDEX64;
  }
}

bool SBTarget::RemoveBreakpointOverride(uint64_t id) {
  if (TargetSP target_sp = GetSP()) {
    return target_sp->RemoveBreakpointResolverOverride(id);
  }
  return false;
}

SBBreakpoint SBTarget::BreakpointCreateByLocation(const char *file,
                                                  uint32_t line) {
  LLDB_INSTRUMENT_VA(this, file, line);

  return SBBreakpoint(
      BreakpointCreateByLocation(SBFileSpec(file, false), line));
}

SBBreakpoint
SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
                                     uint32_t line) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec, line);

  return BreakpointCreateByLocation(sb_file_spec, line, 0);
}

SBBreakpoint
SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
                                     uint32_t line, lldb::addr_t offset) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec, line, offset);

  SBFileSpecList empty_list;
  return BreakpointCreateByLocation(sb_file_spec, line, offset, empty_list);
}

SBBreakpoint
SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
                                     uint32_t line, lldb::addr_t offset,
                                     SBFileSpecList &sb_module_list) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec, line, offset, sb_module_list);

  return BreakpointCreateByLocation(sb_file_spec, line, 0, offset,
                                    sb_module_list);
}

SBBreakpoint SBTarget::BreakpointCreateByLocation(
    const SBFileSpec &sb_file_spec, uint32_t line, uint32_t column,
    lldb::addr_t offset, SBFileSpecList &sb_module_list) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec, line, column, offset, sb_module_list);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP(); target_sp && line != 0) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    const LazyBool check_inlines = eLazyBoolCalculate;
    const LazyBool skip_prologue = eLazyBoolCalculate;
    const bool internal = false;
    const bool hardware = false;
    const LazyBool move_to_nearest_code = eLazyBoolCalculate;
    const FileSpecList *module_list = nullptr;
    if (sb_module_list.GetSize() > 0) {
      module_list = sb_module_list.get();
    }
    sb_bp = target_sp->CreateBreakpoint(
        module_list, *sb_file_spec, line, column, offset, check_inlines,
        skip_prologue, internal, hardware, move_to_nearest_code);
  }

  return sb_bp;
}

SBBreakpoint SBTarget::BreakpointCreateByLocation(
    const SBFileSpec &sb_file_spec, uint32_t line, uint32_t column,
    lldb::addr_t offset, SBFileSpecList &sb_module_list,
    bool move_to_nearest_code) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec, line, column, offset, sb_module_list,
                     move_to_nearest_code);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP(); target_sp && line != 0) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    const LazyBool check_inlines = eLazyBoolCalculate;
    const LazyBool skip_prologue = eLazyBoolCalculate;
    const bool internal = false;
    const bool hardware = false;
    const FileSpecList *module_list = nullptr;
    if (sb_module_list.GetSize() > 0) {
      module_list = sb_module_list.get();
    }
    sb_bp = target_sp->CreateBreakpoint(
        module_list, *sb_file_spec, line, column, offset, check_inlines,
        skip_prologue, internal, hardware,
        move_to_nearest_code ? eLazyBoolYes : eLazyBoolNo);
  }

  return sb_bp;
}

SBBreakpoint SBTarget::BreakpointCreateByName(const char *symbol_name,
                                              const char *module_name) {
  LLDB_INSTRUMENT_VA(this, symbol_name, module_name);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    const bool internal = false;
    const bool hardware = false;
    const LazyBool skip_prologue = eLazyBoolCalculate;
    const lldb::addr_t offset = 0;
    const bool offset_is_insn_count = false;
    if (module_name && module_name[0]) {
      FileSpecList module_spec_list;
      module_spec_list.Append(FileSpec(module_name));
      sb_bp = target_sp->CreateBreakpoint(
          &module_spec_list, nullptr, symbol_name, eFunctionNameTypeAuto,
          eLanguageTypeUnknown, offset, offset_is_insn_count, skip_prologue,
          internal, hardware);
    } else {
      sb_bp = target_sp->CreateBreakpoint(
          nullptr, nullptr, symbol_name, eFunctionNameTypeAuto,
          eLanguageTypeUnknown, offset, offset_is_insn_count, skip_prologue,
          internal, hardware);
    }
  }

  return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateByName(const char *symbol_name,
                                 const SBFileSpecList &module_list,
                                 const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_name, module_list, comp_unit_list);

  lldb::FunctionNameType name_type_mask = eFunctionNameTypeAuto;
  return BreakpointCreateByName(symbol_name, name_type_mask,
                                eLanguageTypeUnknown, module_list,
                                comp_unit_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
    const char *symbol_name, uint32_t name_type_mask,
    const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_name, name_type_mask, module_list,
                     comp_unit_list);

  return BreakpointCreateByName(symbol_name, name_type_mask,
                                eLanguageTypeUnknown, module_list,
                                comp_unit_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
    const char *symbol_name, uint32_t name_type_mask,
    LanguageType symbol_language, const SBFileSpecList &module_list,
    const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_name, name_type_mask, symbol_language,
                     module_list, comp_unit_list);
  return BreakpointCreateByName(symbol_name, name_type_mask, symbol_language, 0,
                                false, module_list, comp_unit_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
    const char *symbol_name, uint32_t name_type_mask,
    LanguageType symbol_language, lldb::addr_t offset,
    bool offset_is_insn_count, const SBFileSpecList &module_list,
    const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_name, name_type_mask, symbol_language, offset,
                     offset_is_insn_count, module_list, comp_unit_list);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP();
      target_sp && symbol_name && symbol_name[0]) {
    const bool internal = false;
    const bool hardware = false;
    const LazyBool skip_prologue = eLazyBoolCalculate;
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
    sb_bp = target_sp->CreateBreakpoint(module_list.get(), comp_unit_list.get(),
                                        symbol_name, mask, symbol_language,
                                        offset, offset_is_insn_count,
                                        skip_prologue, internal, hardware);
  }

  return sb_bp;
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByNames(
    const char *symbol_names[], uint32_t num_names, uint32_t name_type_mask,
    const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_names, num_names, name_type_mask, module_list,
                     comp_unit_list);

  return BreakpointCreateByNames(symbol_names, num_names, name_type_mask,
                                 eLanguageTypeUnknown, module_list,
                                 comp_unit_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByNames(
    const char *symbol_names[], uint32_t num_names, uint32_t name_type_mask,
    LanguageType symbol_language, const SBFileSpecList &module_list,
    const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_names, num_names, name_type_mask,
                     symbol_language, module_list, comp_unit_list);

  return BreakpointCreateByNames(symbol_names, num_names, name_type_mask,
                                 eLanguageTypeUnknown, 0, module_list,
                                 comp_unit_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByNames(
    const char *symbol_names[], uint32_t num_names, uint32_t name_type_mask,
    LanguageType symbol_language, lldb::addr_t offset,
    const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_names, num_names, name_type_mask,
                     symbol_language, offset, module_list, comp_unit_list);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP(); target_sp && num_names > 0) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    const bool internal = false;
    const bool hardware = false;
    FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
    const LazyBool skip_prologue = eLazyBoolCalculate;
    sb_bp = target_sp->CreateBreakpoint(
        module_list.get(), comp_unit_list.get(), symbol_names, num_names, mask,
        symbol_language, offset, skip_prologue, internal, hardware);
  }

  return sb_bp;
}

SBBreakpoint SBTarget::BreakpointCreateByRegex(const char *symbol_name_regex,
                                               const char *module_name) {
  LLDB_INSTRUMENT_VA(this, symbol_name_regex, module_name);

  SBFileSpecList module_spec_list;
  SBFileSpecList comp_unit_list;
  if (module_name && module_name[0]) {
    module_spec_list.Append(FileSpec(module_name));
  }
  return BreakpointCreateByRegex(symbol_name_regex, eLanguageTypeUnknown,
                                 module_spec_list, comp_unit_list);
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateByRegex(const char *symbol_name_regex,
                                  const SBFileSpecList &module_list,
                                  const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_name_regex, module_list, comp_unit_list);

  return BreakpointCreateByRegex(symbol_name_regex, eLanguageTypeUnknown,
                                 module_list, comp_unit_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateByRegex(
    const char *symbol_name_regex, LanguageType symbol_language,
    const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list) {
  LLDB_INSTRUMENT_VA(this, symbol_name_regex, symbol_language, module_list,
                     comp_unit_list);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP();
      target_sp && symbol_name_regex && symbol_name_regex[0]) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    RegularExpression regexp((llvm::StringRef(symbol_name_regex)));
    const bool internal = false;
    const bool hardware = false;
    const LazyBool skip_prologue = eLazyBoolCalculate;

    sb_bp = target_sp->CreateFuncRegexBreakpoint(
        module_list.get(), comp_unit_list.get(), std::move(regexp),
        symbol_language, skip_prologue, internal, hardware);
  }

  return sb_bp;
}

SBBreakpoint SBTarget::BreakpointCreateByAddress(addr_t address) {
  LLDB_INSTRUMENT_VA(this, address);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    const bool hardware = false;
    sb_bp = target_sp->CreateBreakpoint(address, false, hardware);
  }

  return sb_bp;
}

SBBreakpoint SBTarget::BreakpointCreateBySBAddress(SBAddress &sb_address) {
  LLDB_INSTRUMENT_VA(this, sb_address);

  SBBreakpoint sb_bp;
  if (!sb_address.IsValid()) {
    return sb_bp;
  }

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    const bool hardware = false;
    sb_bp = target_sp->CreateBreakpoint(sb_address.ref(), false, hardware);
  }

  return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateBySourceRegex(const char *source_regex,
                                        const lldb::SBFileSpec &source_file,
                                        const char *module_name) {
  LLDB_INSTRUMENT_VA(this, source_regex, source_file, module_name);

  SBFileSpecList module_spec_list;

  if (module_name && module_name[0]) {
    module_spec_list.Append(FileSpec(module_name));
  }

  SBFileSpecList source_file_list;
  if (source_file.IsValid()) {
    source_file_list.Append(source_file);
  }

  return BreakpointCreateBySourceRegex(source_regex, module_spec_list,
                                       source_file_list);
}

lldb::SBBreakpoint SBTarget::BreakpointCreateBySourceRegex(
    const char *source_regex, const SBFileSpecList &module_list,
    const lldb::SBFileSpecList &source_file_list) {
  LLDB_INSTRUMENT_VA(this, source_regex, module_list, source_file_list);

  return BreakpointCreateBySourceRegex(source_regex, module_list,
                                       source_file_list, SBStringList());
}

lldb::SBBreakpoint SBTarget::BreakpointCreateBySourceRegex(
    const char *source_regex, const SBFileSpecList &module_list,
    const lldb::SBFileSpecList &source_file_list,
    const SBStringList &func_names) {
  LLDB_INSTRUMENT_VA(this, source_regex, module_list, source_file_list,
                     func_names);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP();
      target_sp && source_regex && source_regex[0]) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    const bool hardware = false;
    const LazyBool move_to_nearest_code = eLazyBoolCalculate;
    RegularExpression regexp((llvm::StringRef(source_regex)));
    std::unordered_set<std::string> func_names_set;
    for (size_t i = 0; i < func_names.GetSize(); i++) {
      func_names_set.insert(func_names.GetStringAtIndex(i));
    }

    sb_bp = target_sp->CreateSourceRegexBreakpoint(
        module_list.get(), source_file_list.get(), func_names_set,
        std::move(regexp), false, hardware, move_to_nearest_code);
  }

  return sb_bp;
}

lldb::SBBreakpoint
SBTarget::BreakpointCreateForException(lldb::LanguageType language,
                                       bool catch_bp, bool throw_bp) {
  LLDB_INSTRUMENT_VA(this, language, catch_bp, throw_bp);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    const bool hardware = false;
    sb_bp = target_sp->CreateExceptionBreakpoint(language, catch_bp, throw_bp,
                                                  hardware);
  }

  return sb_bp;
}

lldb::SBBreakpoint SBTarget::BreakpointCreateFromScript(
    const char *class_name, SBStructuredData &extra_args,
    const SBFileSpecList &module_list, const SBFileSpecList &file_list,
    bool request_hardware) {
  LLDB_INSTRUMENT_VA(this, class_name, extra_args, module_list, file_list,
                     request_hardware);

  SBBreakpoint sb_bp;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    Status error;

    StructuredData::ObjectSP obj_sp = extra_args.m_impl_up->GetObjectSP();
    sb_bp =
        target_sp->CreateScriptedBreakpoint(class_name,
                                            module_list.get(),
                                            file_list.get(),
                                            false, /* internal */
                                            request_hardware,
                                            obj_sp,
                                            &error);
  }

  return sb_bp;
}

uint32_t SBTarget::GetNumBreakpoints() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    // The breakpoint list is thread safe, no need to lock
    return target_sp->GetBreakpointList().GetSize();
  }
  return 0;
}

SBBreakpoint SBTarget::GetBreakpointAtIndex(uint32_t idx) const {
  LLDB_INSTRUMENT_VA(this, idx);

  SBBreakpoint sb_breakpoint;
  if (TargetSP target_sp = GetSP()) {
    // The breakpoint list is thread safe, no need to lock
    sb_breakpoint = target_sp->GetBreakpointList().GetBreakpointAtIndex(idx);
  }
  return sb_breakpoint;
}

bool SBTarget::BreakpointDelete(break_id_t bp_id) {
  LLDB_INSTRUMENT_VA(this, bp_id);

  bool result = false;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    result = target_sp->RemoveBreakpointByID(bp_id);
  }

  return result;
}

SBBreakpoint SBTarget::FindBreakpointByID(break_id_t bp_id) {
  LLDB_INSTRUMENT_VA(this, bp_id);

  SBBreakpoint sb_breakpoint;
  if (TargetSP target_sp = GetSP();
      target_sp && bp_id != LLDB_INVALID_BREAK_ID) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    sb_breakpoint = target_sp->GetBreakpointByID(bp_id);
  }

  return sb_breakpoint;
}

bool SBTarget::FindBreakpointsByName(const char *name,
                                     SBBreakpointList &bkpts) {
  LLDB_INSTRUMENT_VA(this, name, bkpts);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    llvm::Expected<std::vector<BreakpointSP>> expected_vector =
        target_sp->GetBreakpointList().FindBreakpointsByName(name);
    if (!expected_vector) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Breakpoints), expected_vector.takeError(),
                     "invalid breakpoint name: {0}");
      return false;
    }
    for (BreakpointSP bkpt_sp : *expected_vector) {
      bkpts.AppendByID(bkpt_sp->GetID());
    }
  }
  return true;
}

void SBTarget::GetBreakpointNames(SBStringList &names) {
  LLDB_INSTRUMENT_VA(this, names);

  names.Clear();

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    std::vector<std::string> name_vec;
    target_sp->GetBreakpointNames(name_vec);
    for (const auto &name : name_vec)
      names.AppendString(name.c_str());
  }
}

void SBTarget::DeleteBreakpointName(const char *name) {
  LLDB_INSTRUMENT_VA(this, name);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    target_sp->DeleteBreakpointName(llvm::StringRef(name));
  }
}

bool SBTarget::EnableAllBreakpoints() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    target_sp->EnableAllowedBreakpoints();
    return true;
  }
  return false;
}

bool SBTarget::DisableAllBreakpoints() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    target_sp->DisableAllowedBreakpoints();
    return true;
  }
  return false;
}

bool SBTarget::DeleteAllBreakpoints() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    target_sp->RemoveAllowedBreakpoints();
    return true;
  }
  return false;
}

lldb::SBError SBTarget::BreakpointsCreateFromFile(SBFileSpec &source_file,
                                                  SBBreakpointList &new_bps) {
  LLDB_INSTRUMENT_VA(this, source_file, new_bps);

  SBStringList empty_name_list;
  return BreakpointsCreateFromFile(source_file, empty_name_list, new_bps);
}

lldb::SBError SBTarget::BreakpointsCreateFromFile(SBFileSpec &source_file,
                                                  SBStringList &matching_names,
                                                  SBBreakpointList &new_bps) {
  LLDB_INSTRUMENT_VA(this, source_file, matching_names, new_bps);

  SBError sberr;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);

    BreakpointIDList bp_ids;

    std::vector<std::string> name_vector;
    size_t num_names = matching_names.GetSize();
    for (size_t i = 0; i < num_names; i++)
      name_vector.push_back(matching_names.GetStringAtIndex(i));

    sberr.ref() = target_sp->CreateBreakpointsFromFile(source_file.ref(),
                                                       name_vector, bp_ids);
    if (sberr.Fail())
      return sberr;

    size_t num_bkpts = bp_ids.GetSize();
    for (size_t i = 0; i < num_bkpts; i++) {
      BreakpointID bp_id = bp_ids.GetBreakpointIDAtIndex(i);
      new_bps.AppendByID(bp_id.GetBreakpointID());
    }
  } else {
    sberr.SetErrorString(
        "BreakpointCreateFromFile called with invalid target.");
  }
  return sberr;
}

lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file) {
  LLDB_INSTRUMENT_VA(this, dest_file);

  SBError sberr;
  if (TargetSP target_sp = GetSP()) {
    SBBreakpointList bkpt_list(*this);
    return BreakpointsWriteToFile(dest_file, bkpt_list);
  }
  sberr.SetErrorString("BreakpointWriteToFile called with invalid target.");
  return sberr;
}

lldb::SBError SBTarget::BreakpointsWriteToFile(SBFileSpec &dest_file,
                                               SBBreakpointList &bkpt_list,
                                               bool append) {
  LLDB_INSTRUMENT_VA(this, dest_file, bkpt_list, append);

  SBError sberr;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    BreakpointIDList bp_id_list;
    bkpt_list.CopyToBreakpointIDList(bp_id_list);
    sberr.ref() = target_sp->SerializeBreakpointsToFile(dest_file.ref(),
                                                        bp_id_list, append);
  } else {
    sberr.SetErrorString("BreakpointWriteToFile called with invalid target.");
  }
  return sberr;
}

uint32_t SBTarget::GetNumWatchpoints() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    // The watchpoint list is thread safe, no need to lock
    return target_sp->GetWatchpointList().GetSize();
  }
  return 0;
}

SBWatchpoint SBTarget::GetWatchpointAtIndex(uint32_t idx) const {
  LLDB_INSTRUMENT_VA(this, idx);

  SBWatchpoint sb_watchpoint;
  if (TargetSP target_sp = GetSP()) {
    // The watchpoint list is thread safe, no need to lock
    sb_watchpoint.SetSP(target_sp->GetWatchpointList().GetByIndex(idx));
  }
  return sb_watchpoint;
}

bool SBTarget::DeleteWatchpoint(watch_id_t wp_id) {
  LLDB_INSTRUMENT_VA(this, wp_id);

  bool result = false;
  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    std::unique_lock<std::recursive_mutex> lock;
    target_sp->GetWatchpointList().GetListMutex(lock);
    result = target_sp->RemoveWatchpointByID(wp_id);
  }

  return result;
}

SBWatchpoint SBTarget::FindWatchpointByID(lldb::watch_id_t wp_id) {
  LLDB_INSTRUMENT_VA(this, wp_id);

  SBWatchpoint sb_watchpoint;
  lldb::WatchpointSP watchpoint_sp;
  if (TargetSP target_sp = GetSP();
      target_sp && wp_id != LLDB_INVALID_WATCH_ID) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    std::unique_lock<std::recursive_mutex> lock;
    target_sp->GetWatchpointList().GetListMutex(lock);
    watchpoint_sp = target_sp->GetWatchpointList().FindByID(wp_id);
    sb_watchpoint.SetSP(watchpoint_sp);
  }

  return sb_watchpoint;
}

lldb::SBWatchpoint SBTarget::WatchAddress(lldb::addr_t addr, size_t size,
                                          bool read, bool modify,
                                          SBError &error) {
  LLDB_INSTRUMENT_VA(this, addr, size, read, write, error);

  SBWatchpointOptions options;
  options.SetWatchpointTypeRead(read);
  if (modify)
    options.SetWatchpointTypeWrite(eWatchpointWriteTypeOnModify);
  return WatchpointCreateByAddress(addr, size, options, error);
}

lldb::SBWatchpoint
SBTarget::WatchpointCreateByAddress(lldb::addr_t addr, size_t size,
                                    SBWatchpointOptions options,
                                    SBError &error) {
  LLDB_INSTRUMENT_VA(this, addr, size, options, error);

  SBWatchpoint sb_watchpoint;
  lldb::WatchpointSP watchpoint_sp;
  uint32_t watch_type = 0;
  if (options.GetWatchpointTypeRead())
    watch_type |= LLDB_WATCH_TYPE_READ;
  if (options.GetWatchpointTypeWrite() == eWatchpointWriteTypeAlways)
    watch_type |= LLDB_WATCH_TYPE_WRITE;
  if (options.GetWatchpointTypeWrite() == eWatchpointWriteTypeOnModify)
    watch_type |= LLDB_WATCH_TYPE_MODIFY;
  if (watch_type == 0) {
    error.SetErrorString("Can't create a watchpoint that is neither read nor "
                         "write nor modify.");
    return sb_watchpoint;
  }

  if (TargetSP target_sp = GetSP();
      target_sp && addr != LLDB_INVALID_ADDRESS && size > 0) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    // Target::CreateWatchpoint() is thread safe.
    Status cw_error;
    // This API doesn't take in a type, so we can't figure out what it is.
    CompilerType *type = nullptr;
    watchpoint_sp =
        target_sp->CreateWatchpoint(addr, size, type, watch_type, cw_error);
    error.SetError(std::move(cw_error));
    sb_watchpoint.SetSP(watchpoint_sp);
  }

  return sb_watchpoint;
}

bool SBTarget::EnableAllWatchpoints() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    std::unique_lock<std::recursive_mutex> lock;
    target_sp->GetWatchpointList().GetListMutex(lock);
    target_sp->EnableAllWatchpoints();
    return true;
  }
  return false;
}

bool SBTarget::DisableAllWatchpoints() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    std::unique_lock<std::recursive_mutex> lock;
    target_sp->GetWatchpointList().GetListMutex(lock);
    target_sp->DisableAllWatchpoints();
    return true;
  }
  return false;
}

SBValue SBTarget::CreateValueFromAddress(const char *name, SBAddress addr,
                                         SBType type) {
  LLDB_INSTRUMENT_VA(this, name, addr, type);

  SBValue sb_value;
  lldb::ValueObjectSP new_value_sp;
  if (IsValid() && name && *name && addr.IsValid() && type.IsValid()) {
    lldb::addr_t load_addr(addr.GetLoadAddress(*this));
    ExecutionContext exe_ctx(
        ExecutionContextRef(ExecutionContext(m_opaque_sp.get(), false)));
    CompilerType ast_type(type.GetSP()->GetCompilerType(true));
    new_value_sp = ValueObject::CreateValueObjectFromAddress(name, load_addr,
                                                             exe_ctx, ast_type);
  }
  sb_value.SetSP(new_value_sp);
  return sb_value;
}

lldb::SBValue SBTarget::CreateValueFromData(const char *name, lldb::SBData data,
                                            lldb::SBType type) {
  LLDB_INSTRUMENT_VA(this, name, data, type);

  SBValue sb_value;
  lldb::ValueObjectSP new_value_sp;
  if (IsValid() && name && *name && data.IsValid() && type.IsValid()) {
    DataExtractorSP extractor(*data);
    ExecutionContext exe_ctx(
        ExecutionContextRef(ExecutionContext(m_opaque_sp.get(), false)));
    CompilerType ast_type(type.GetSP()->GetCompilerType(true));
    new_value_sp = ValueObject::CreateValueObjectFromData(name, *extractor,
                                                          exe_ctx, ast_type);
  }
  sb_value.SetSP(new_value_sp);
  return sb_value;
}

lldb::SBValue SBTarget::CreateValueFromExpression(const char *name,
                                                  const char *expr) {
  LLDB_INSTRUMENT_VA(this, name, expr);

  SBValue sb_value;
  lldb::ValueObjectSP new_value_sp;
  if (IsValid() && name && *name && expr && *expr) {
    ExecutionContext exe_ctx(
        ExecutionContextRef(ExecutionContext(m_opaque_sp.get(), false)));
    new_value_sp =
        ValueObject::CreateValueObjectFromExpression(name, expr, exe_ctx);
  }
  sb_value.SetSP(new_value_sp);
  return sb_value;
}

bool SBTarget::DeleteAllWatchpoints() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    std::unique_lock<std::recursive_mutex> lock;
    target_sp->GetWatchpointList().GetListMutex(lock);
    target_sp->RemoveAllWatchpoints();
    return true;
  }
  return false;
}

void SBTarget::AppendImageSearchPath(const char *from, const char *to,
                                     lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, from, to, error);

  if (TargetSP target_sp = GetSP()) {
    llvm::StringRef srFrom = from, srTo = to;
    if (srFrom.empty())
      return error.SetErrorString("<from> path can't be empty");
    if (srTo.empty())
      return error.SetErrorString("<to> path can't be empty");

    target_sp->GetImageSearchPathList().Append(srFrom, srTo, true);
  } else {
    error.SetErrorString("invalid target");
  }
}

lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
                                   const char *uuid_cstr) {
  LLDB_INSTRUMENT_VA(this, path, triple, uuid_cstr);

  return AddModule(path, triple, uuid_cstr, nullptr);
}

lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
                                   const char *uuid_cstr, const char *symfile) {
  LLDB_INSTRUMENT_VA(this, path, triple, uuid_cstr, symfile);

  if (TargetSP target_sp = GetSP()) {
    ModuleSpec module_spec;
    if (path)
      module_spec.GetFileSpec().SetFile(path, FileSpec::Style::native);

    if (uuid_cstr)
      module_spec.GetUUID().SetFromStringRef(uuid_cstr);

    if (triple)
      module_spec.GetArchitecture() = Platform::GetAugmentedArchSpec(
          target_sp->GetPlatform().get(), triple);
    else
      module_spec.GetArchitecture() = target_sp->GetArchitecture();

    if (symfile)
      module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native);

    SBModuleSpec sb_modulespec(module_spec);

    return AddModule(sb_modulespec);
  }
  return SBModule();
}

lldb::SBModule SBTarget::AddModule(const SBModuleSpec &module_spec) {
  LLDB_INSTRUMENT_VA(this, module_spec);

  lldb::SBModule sb_module;
  if (TargetSP target_sp = GetSP()) {
    sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up,
                                                 true /* notify */));
    if (!sb_module.IsValid() && module_spec.m_opaque_up->GetUUID().IsValid()) {
      Status error;
      if (PluginManager::DownloadObjectAndSymbolFile(*module_spec.m_opaque_up,
                                                     error,
                                                     /* force_lookup */ true)) {
        if (FileSystem::Instance().Exists(
                module_spec.m_opaque_up->GetFileSpec())) {
          sb_module.SetSP(target_sp->GetOrCreateModule(*module_spec.m_opaque_up,
                                                       true /* notify */));
        }
      }
    }

    // If the target hasn't initialized any architecture yet, use the
    // binary's architecture.
    if (sb_module.IsValid() && !target_sp->GetArchitecture().IsValid() &&
        sb_module.GetSP()->GetArchitecture().IsValid())
      target_sp->SetArchitecture(sb_module.GetSP()->GetArchitecture());
  }
  return sb_module;
}

bool SBTarget::AddModule(lldb::SBModule &module) {
  LLDB_INSTRUMENT_VA(this, module);

  if (TargetSP target_sp = GetSP()) {
    target_sp->GetImages().AppendIfNeeded(module.GetSP());
    return true;
  }
  return false;
}

uint32_t SBTarget::GetNumModules() const {
  LLDB_INSTRUMENT_VA(this);

  uint32_t num = 0;
  if (TargetSP target_sp = GetSP()) {
    // The module list is thread safe, no need to lock
    num = target_sp->GetImages().GetSize();
  }

  return num;
}

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

  m_opaque_sp.reset();
}

SBModule SBTarget::FindModule(const SBFileSpec &sb_file_spec) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec);

  SBModule sb_module;
  if (TargetSP target_sp = GetSP(); target_sp && sb_file_spec.IsValid()) {
    ModuleSpec module_spec(*sb_file_spec);
    // The module list is thread safe, no need to lock
    sb_module.SetSP(target_sp->GetImages().FindFirstModule(module_spec));
  }
  return sb_module;
}

SBModule SBTarget::FindModule(const SBModuleSpec &sb_module_spec) const {
  LLDB_INSTRUMENT_VA(this, sb_module_spec);

  SBModule sb_module;
  if (TargetSP target_sp = GetSP(); target_sp && sb_module_spec.IsValid()) {
    // The module list is thread safe, no need to lock.
    sb_module.SetSP(
        target_sp->GetImages().FindFirstModule(*sb_module_spec.m_opaque_up));
  }
  return sb_module;
}

SBSymbolContextList SBTarget::FindCompileUnits(const SBFileSpec &sb_file_spec) {
  LLDB_INSTRUMENT_VA(this, sb_file_spec);

  SBSymbolContextList sb_sc_list;
  if (TargetSP target_sp = GetSP(); target_sp && sb_file_spec.IsValid())
    target_sp->GetImages().FindCompileUnits(*sb_file_spec, *sb_sc_list);
  return sb_sc_list;
}

lldb::ByteOrder SBTarget::GetByteOrder() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return target_sp->GetArchitecture().GetByteOrder();
  return eByteOrderInvalid;
}

const char *SBTarget::GetTriple() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    const std::string &triple = target_sp->GetArchitecture().GetTriple().str();
    // Unique the string so we don't run into ownership issues since the const
    // strings put the string into the string pool once and the strings never
    // comes out
    ConstString const_triple(triple);
    return const_triple.GetCString();
  }
  return nullptr;
}

const char *SBTarget::GetArchName() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    llvm::StringRef arch_name =
        target_sp->GetArchitecture().GetTriple().getArchName();
    ConstString const_arch_name(arch_name);

    return const_arch_name.GetCString();
  }
  return nullptr;
}

const char *SBTarget::GetABIName() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    ConstString const_name(target_sp->GetABIName());
    return const_name.GetCString();
  }
  return nullptr;
}

const char *SBTarget::GetLabel() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return ConstString(target_sp->GetLabel()).AsCString(nullptr);
  return nullptr;
}

lldb::user_id_t SBTarget::GetGloballyUniqueID() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return target_sp->GetGloballyUniqueID();
  return LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID;
}

const char *SBTarget::GetTargetSessionName() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return ConstString(target_sp->GetTargetSessionName()).AsCString(nullptr);
  return nullptr;
}

SBError SBTarget::SetLabel(const char *label) {
  LLDB_INSTRUMENT_VA(this, label);

  if (TargetSP target_sp = GetSP())
    return Status::FromError(target_sp->SetLabel(label));
  return Status::FromErrorString("Couldn't get internal target object.");
}

uint32_t SBTarget::GetMinimumOpcodeByteSize() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return target_sp->GetArchitecture().GetMinimumOpcodeByteSize();
  return 0;
}

uint32_t SBTarget::GetMaximumOpcodeByteSize() const {
  LLDB_INSTRUMENT_VA(this);

  TargetSP target_sp(GetSP());
  if (target_sp)
    return target_sp->GetArchitecture().GetMaximumOpcodeByteSize();

  return 0;
}

uint32_t SBTarget::GetDataByteSize() {
  LLDB_INSTRUMENT_VA(this);

  return 1;
}

uint32_t SBTarget::GetCodeByteSize() {
  LLDB_INSTRUMENT_VA(this);

  return 1;
}

uint32_t SBTarget::GetMaximumNumberOfChildrenToDisplay() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return target_sp->GetMaximumNumberOfChildrenToDisplay();
  return 0;
}

uint32_t SBTarget::GetAddressByteSize() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return target_sp->GetArchitecture().GetAddressByteSize();
  return sizeof(void *);
}

SBModule SBTarget::GetModuleAtIndex(uint32_t idx) {
  LLDB_INSTRUMENT_VA(this, idx);

  SBModule sb_module;
  ModuleSP module_sp;
  if (TargetSP target_sp = GetSP()) {
    // The module list is thread safe, no need to lock
    module_sp = target_sp->GetImages().GetModuleAtIndex(idx);
    sb_module.SetSP(module_sp);
  }

  return sb_module;
}

bool SBTarget::RemoveModule(lldb::SBModule module) {
  LLDB_INSTRUMENT_VA(this, module);

  if (TargetSP target_sp = GetSP())
    return target_sp->GetImages().Remove(module.GetSP());
  return false;
}

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

  if (TargetSP target_sp = GetSP()) {
    SBBroadcaster broadcaster(target_sp.get(), false);
    return broadcaster;
  }
  return SBBroadcaster();
}

bool SBTarget::GetDescription(SBStream &description,
                              lldb::DescriptionLevel description_level) {
  LLDB_INSTRUMENT_VA(this, description, description_level);

  Stream &strm = description.ref();

  if (TargetSP target_sp = GetSP()) {
    target_sp->Dump(&strm, description_level);
  } else
    strm.PutCString("No value");

  return true;
}

lldb::SBSymbolContextList SBTarget::FindFunctions(const char *name,
                                                  uint32_t name_type_mask) {
  LLDB_INSTRUMENT_VA(this, name, name_type_mask);

  lldb::SBSymbolContextList sb_sc_list;
  if (!name || !name[0])
    return sb_sc_list;

  if (TargetSP target_sp = GetSP()) {
    ModuleFunctionSearchOptions function_options;
    function_options.include_symbols = true;
    function_options.include_inlines = true;

    FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
    target_sp->GetImages().FindFunctions(ConstString(name), mask,
                                         function_options, *sb_sc_list);
  }
  return sb_sc_list;
}

lldb::SBSymbolContextList SBTarget::FindGlobalFunctions(const char *name,
                                                        uint32_t max_matches,
                                                        MatchType matchtype) {
  LLDB_INSTRUMENT_VA(this, name, max_matches, matchtype);

  lldb::SBSymbolContextList sb_sc_list;
  if (name && name[0]) {
    llvm::StringRef name_ref(name);
    if (TargetSP target_sp = GetSP()) {
      ModuleFunctionSearchOptions function_options;
      function_options.include_symbols = true;
      function_options.include_inlines = true;

      std::string regexstr;
      switch (matchtype) {
      case eMatchTypeRegex:
        target_sp->GetImages().FindFunctions(RegularExpression(name_ref),
                                             function_options, *sb_sc_list);
        break;
      case eMatchTypeRegexInsensitive:
        target_sp->GetImages().FindFunctions(
            RegularExpression(name_ref, llvm::Regex::RegexFlags::IgnoreCase),
            function_options, *sb_sc_list);
        break;
      case eMatchTypeStartsWith:
        regexstr = llvm::Regex::escape(name) + ".*";
        target_sp->GetImages().FindFunctions(RegularExpression(regexstr),
                                             function_options, *sb_sc_list);
        break;
      default:
        target_sp->GetImages().FindFunctions(ConstString(name),
                                             eFunctionNameTypeAny,
                                             function_options, *sb_sc_list);
        break;
      }
    }
  }
  return sb_sc_list;
}

lldb::SBType SBTarget::FindExpressionTypeForLanguage(
    const char *typename_cstr, lldb::LanguageType language, SBError &sb_error) {
  LLDB_INSTRUMENT_VA(this, typename_cstr, language, sb_error);
  sb_error.Clear();

  TargetSP target_sp = GetSP();
  if (!target_sp) {
    sb_error.SetErrorString("no target.");
    return {};
  }

  if (!typename_cstr || !typename_cstr[0]) {
    sb_error.SetErrorString("empty type name for search.");
    return {};
  }

  if (language == eLanguageTypeUnknown) {
    sb_error.SetErrorString("eLanguageTypeUnknown can't define expression "
                            "types.");
    return {};
  }

  PersistentExpressionState *persistent =
      target_sp->GetPersistentExpressionStateForLanguage(language);

  if (!persistent) {
    sb_error.SetErrorString(
        llvm::formatv("language {0} does not support expression defined types",
                      language)
            .str()
            .c_str());
    return {};
  }

  ConstString const_typename(typename_cstr);
  std::optional<CompilerType> type_op =
      persistent->GetCompilerTypeFromPersistentDecl(const_typename);
  if (type_op && (*type_op)) {
    return SBType(*type_op);
  }
  sb_error.SetErrorString(
      llvm::formatv("no type {0} found in expression types for language {1}",
                    typename_cstr, language)
          .str()
          .c_str());
  return {};
}

lldb::SBValue
SBTarget::FindExpressionVariableForLanguage(const char *varname_cstr,
                                            lldb::LanguageType language) {
  LLDB_INSTRUMENT_VA(this, varname_cstr, language);
  TargetSP target_sp = GetSP();
  if (!target_sp)
    return ValueObjectConstResult::Create(
        nullptr,
        Status::FromErrorStringWithFormatv(
            "no variable {0} found for language {1}", varname_cstr, language));

  if (!varname_cstr || !varname_cstr[0])
    return ValueObjectConstResult::Create(
        target_sp.get(),
        Status::FromErrorString("empty variable name for search."));

  if (language == eLanguageTypeUnknown)
    return ValueObjectConstResult::Create(
        nullptr, Status::FromErrorString("eLanguageTypeUnknown doesn't support "
                                         "expression variables."));

  PersistentExpressionState *persistent =
      target_sp->GetPersistentExpressionStateForLanguage(language);
  if (!persistent) {
    return ValueObjectConstResult::Create(
        target_sp.get(),
        Status::FromErrorStringWithFormatv(
            "language: {0} doesn't support expression variables.", language));
  }

  ConstString const_varname(varname_cstr);
  lldb::ExpressionVariableSP expr_var_sp =
      persistent->GetVariable(const_varname);
  if (expr_var_sp)
    return expr_var_sp->GetValueObject();

  return ValueObjectConstResult::Create(
      target_sp.get(),
      Status::FromErrorStringWithFormatv(
          "no variable {0} found for language {1}", varname_cstr, language));
}

lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) {
  LLDB_INSTRUMENT_VA(this, typename_cstr);

  if (TargetSP target_sp = GetSP();
      target_sp && typename_cstr && typename_cstr[0]) {
    ConstString const_typename(typename_cstr);
    TypeQuery query(const_typename.GetStringRef(),
                    TypeQueryOptions::e_find_one);
    TypeResults results;
    target_sp->GetImages().FindTypes(/*search_first=*/nullptr, query, results);
    if (TypeSP type_sp = results.GetFirstType())
      return SBType(type_sp);
    // Didn't find the type in the symbols; Try the loaded language runtimes.
    if (auto process_sp = target_sp->GetProcessSP()) {
      for (auto *runtime : process_sp->GetLanguageRuntimes()) {
        if (auto vendor = runtime->GetDeclVendor()) {
          auto types = vendor->FindTypes(const_typename, /*max_matches*/ 1);
          if (!types.empty())
            return SBType(types.front());
        }
      }
    }

    // No matches, search for basic typename matches.
    for (auto type_system_sp : target_sp->GetScratchTypeSystems())
      if (auto type = type_system_sp->GetBuiltinTypeByName(const_typename))
        return SBType(type);
  }

  return SBType();
}

SBType SBTarget::GetBasicType(lldb::BasicType type) {
  LLDB_INSTRUMENT_VA(this, type);

  if (TargetSP target_sp = GetSP()) {
    for (auto type_system_sp : target_sp->GetScratchTypeSystems())
      if (auto compiler_type = type_system_sp->GetBasicTypeFromAST(type))
        return SBType(compiler_type);
  }
  return SBType();
}

lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) {
  LLDB_INSTRUMENT_VA(this, typename_cstr);

  SBTypeList sb_type_list;
  if (TargetSP target_sp = GetSP();
      target_sp && typename_cstr && typename_cstr[0]) {
    ModuleList &images = target_sp->GetImages();
    ConstString const_typename(typename_cstr);
    TypeQuery query(typename_cstr);
    TypeResults results;
    images.FindTypes(nullptr, query, results);
    for (const TypeSP &type_sp : results.GetTypeMap().Types())
      sb_type_list.Append(SBType(type_sp));

    // Try the loaded language runtimes
    if (ProcessSP process_sp = target_sp->GetProcessSP()) {
      for (auto *runtime : process_sp->GetLanguageRuntimes()) {
        if (auto *vendor = runtime->GetDeclVendor()) {
          auto types =
              vendor->FindTypes(const_typename, /*max_matches*/ UINT32_MAX);
          for (auto type : types)
            sb_type_list.Append(SBType(type));
        }
      }
    }

    if (sb_type_list.GetSize() == 0) {
      // No matches, search for basic typename matches
      for (auto type_system_sp : target_sp->GetScratchTypeSystems())
        if (auto compiler_type =
                type_system_sp->GetBuiltinTypeByName(const_typename))
          sb_type_list.Append(SBType(compiler_type));
    }
  }
  return sb_type_list;
}

SBValueList SBTarget::FindGlobalVariables(const char *name,
                                          uint32_t max_matches) {
  LLDB_INSTRUMENT_VA(this, name, max_matches);

  SBValueList sb_value_list;

  if (TargetSP target_sp = GetSP(); target_sp && name) {
    VariableList variable_list;
    target_sp->GetImages().FindGlobalVariables(ConstString(name), max_matches,
                                               variable_list);
    if (!variable_list.Empty()) {
      ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
      if (exe_scope == nullptr)
        exe_scope = target_sp.get();
      for (const VariableSP &var_sp : variable_list) {
        lldb::ValueObjectSP valobj_sp(
            ValueObjectVariable::Create(exe_scope, var_sp));
        if (valobj_sp)
          sb_value_list.Append(SBValue(valobj_sp));
      }
    }
  }

  return sb_value_list;
}

SBValueList SBTarget::FindGlobalVariables(const char *name,
                                          uint32_t max_matches,
                                          MatchType matchtype) {
  LLDB_INSTRUMENT_VA(this, name, max_matches, matchtype);

  SBValueList sb_value_list;

  if (TargetSP target_sp = GetSP(); target_sp && name) {
    llvm::StringRef name_ref(name);
    VariableList variable_list;

    std::string regexstr;
    switch (matchtype) {
    case eMatchTypeNormal:
      target_sp->GetImages().FindGlobalVariables(ConstString(name), max_matches,
                                                 variable_list);
      break;
    case eMatchTypeRegex:
      target_sp->GetImages().FindGlobalVariables(RegularExpression(name_ref),
                                                 max_matches, variable_list);
      break;
    case eMatchTypeRegexInsensitive:
      target_sp->GetImages().FindGlobalVariables(
          RegularExpression(name_ref, llvm::Regex::IgnoreCase), max_matches,
          variable_list);
      break;
    case eMatchTypeStartsWith:
      regexstr = "^" + llvm::Regex::escape(name) + ".*";
      target_sp->GetImages().FindGlobalVariables(RegularExpression(regexstr),
                                                 max_matches, variable_list);
      break;
    }
    if (!variable_list.Empty()) {
      ExecutionContextScope *exe_scope = target_sp->GetProcessSP().get();
      if (exe_scope == nullptr)
        exe_scope = target_sp.get();
      for (const VariableSP &var_sp : variable_list) {
        lldb::ValueObjectSP valobj_sp(
            ValueObjectVariable::Create(exe_scope, var_sp));
        if (valobj_sp)
          sb_value_list.Append(SBValue(valobj_sp));
      }
    }
  }

  return sb_value_list;
}

lldb::SBValue SBTarget::FindFirstGlobalVariable(const char *name) {
  LLDB_INSTRUMENT_VA(this, name);

  SBValueList sb_value_list(FindGlobalVariables(name, 1));
  if (sb_value_list.IsValid() && sb_value_list.GetSize() > 0)
    return sb_value_list.GetValueAtIndex(0);
  return SBValue();
}

SBSourceManager SBTarget::GetSourceManager() {
  LLDB_INSTRUMENT_VA(this);

  SBSourceManager source_manager(*this);
  return source_manager;
}

lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
                                                   uint32_t count) {
  LLDB_INSTRUMENT_VA(this, base_addr, count);

  return ReadInstructions(base_addr, count, nullptr);
}

lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
                                                   uint32_t count,
                                                   const char *flavor_string) {
  LLDB_INSTRUMENT_VA(this, base_addr, count, flavor_string);

  SBInstructionList sb_instructions;

  if (TargetSP target_sp = GetSP()) {
    if (Address *addr_ptr = base_addr.get()) {
      if (llvm::Expected<DisassemblerSP> disassembler =
              target_sp->ReadInstructions(*addr_ptr, count, flavor_string)) {
        sb_instructions.SetDisassembler(*disassembler);
      } else {
        LLDB_LOG_ERROR(GetLog(LLDBLog::API), disassembler.takeError(), "{0}");
      }
    }
  }

  return sb_instructions;
}

lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress start_addr,
                                                   lldb::SBAddress end_addr,
                                                   const char *flavor_string) {
  LLDB_INSTRUMENT_VA(this, start_addr, end_addr, flavor_string);

  SBInstructionList sb_instructions;

  if (TargetSP target_sp = GetSP()) {
    lldb::addr_t start_load_addr = start_addr.GetLoadAddress(*this);
    lldb::addr_t end_load_addr = end_addr.GetLoadAddress(*this);
    if (end_load_addr > start_load_addr) {
      lldb::addr_t size = end_load_addr - start_load_addr;

      AddressRange range(start_load_addr, size);
      const bool force_live_memory = true;
      sb_instructions.SetDisassembler(Disassembler::DisassembleRange(
          target_sp->GetArchitecture(), nullptr, flavor_string,
          target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
          *target_sp, range, force_live_memory));
    }
  }
  return sb_instructions;
}

lldb::SBInstructionList SBTarget::GetInstructions(lldb::SBAddress base_addr,
                                                  const void *buf,
                                                  size_t size) {
  LLDB_INSTRUMENT_VA(this, base_addr, buf, size);

  return GetInstructionsWithFlavor(base_addr, nullptr, buf, size);
}

lldb::SBInstructionList
SBTarget::GetInstructionsWithFlavor(lldb::SBAddress base_addr,
                                    const char *flavor_string, const void *buf,
                                    size_t size) {
  LLDB_INSTRUMENT_VA(this, base_addr, flavor_string, buf, size);

  SBInstructionList sb_instructions;

  if (TargetSP target_sp = GetSP()) {
    Address addr;

    if (base_addr.get())
      addr = *base_addr.get();

    constexpr bool data_from_file = true;
    if (!flavor_string || flavor_string[0] == '\0') {
      // FIXME - we don't have the mechanism in place to do per-architecture
      // settings.  But since we know that for now we only support flavors on
      // x86 & x86_64,
      const llvm::Triple::ArchType arch =
          target_sp->GetArchitecture().GetTriple().getArch();
      if (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64)
        flavor_string = target_sp->GetDisassemblyFlavor();
    }

    sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
        target_sp->GetArchitecture(), nullptr, flavor_string,
        target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
        addr, buf, size, UINT32_MAX, data_from_file));
  }

  return sb_instructions;
}

lldb::SBInstructionList SBTarget::GetInstructions(lldb::addr_t base_addr,
                                                  const void *buf,
                                                  size_t size) {
  LLDB_INSTRUMENT_VA(this, base_addr, buf, size);

  return GetInstructionsWithFlavor(ResolveLoadAddress(base_addr), nullptr, buf,
                                   size);
}

lldb::SBInstructionList
SBTarget::GetInstructionsWithFlavor(lldb::addr_t base_addr,
                                    const char *flavor_string, const void *buf,
                                    size_t size) {
  LLDB_INSTRUMENT_VA(this, base_addr, flavor_string, buf, size);

  return GetInstructionsWithFlavor(ResolveLoadAddress(base_addr), flavor_string,
                                   buf, size);
}

SBError SBTarget::SetSectionLoadAddress(lldb::SBSection section,
                                        lldb::addr_t section_base_addr) {
  LLDB_INSTRUMENT_VA(this, section, section_base_addr);

  SBError sb_error;
  if (TargetSP target_sp = GetSP()) {
    if (!section.IsValid()) {
      sb_error.SetErrorStringWithFormat("invalid section");
    } else {
      SectionSP section_sp(section.GetSP());
      if (section_sp) {
        if (section_sp->IsThreadSpecific()) {
          sb_error.SetErrorString(
              "thread specific sections are not yet supported");
        } else {
          ProcessSP process_sp(target_sp->GetProcessSP());
          if (target_sp->SetSectionLoadAddress(section_sp, section_base_addr)) {
            ModuleSP module_sp(section_sp->GetModule());
            if (module_sp) {
              ModuleList module_list;
              module_list.Append(module_sp);
              target_sp->ModulesDidLoad(module_list);
            }
            // Flush info in the process (stack frames, etc)
            if (process_sp)
              process_sp->Flush();
          }
        }
      }
    }
  } else {
    sb_error.SetErrorString("invalid target");
  }
  return sb_error;
}

SBError SBTarget::ClearSectionLoadAddress(lldb::SBSection section) {
  LLDB_INSTRUMENT_VA(this, section);

  SBError sb_error;

  if (TargetSP target_sp = GetSP()) {
    if (!section.IsValid()) {
      sb_error.SetErrorStringWithFormat("invalid section");
    } else {
      SectionSP section_sp(section.GetSP());
      if (section_sp) {
        ProcessSP process_sp(target_sp->GetProcessSP());
        if (target_sp->SetSectionUnloaded(section_sp)) {
          ModuleSP module_sp(section_sp->GetModule());
          if (module_sp) {
            ModuleList module_list;
            module_list.Append(module_sp);
            target_sp->ModulesDidUnload(module_list, false);
          }
          // Flush info in the process (stack frames, etc)
          if (process_sp)
            process_sp->Flush();
        }
      } else {
        sb_error.SetErrorStringWithFormat("invalid section");
      }
    }
  } else {
    sb_error.SetErrorStringWithFormat("invalid target");
  }
  return sb_error;
}

SBError SBTarget::SetModuleLoadAddress(lldb::SBModule module,
                                       int64_t slide_offset) {
  LLDB_INSTRUMENT_VA(this, module, slide_offset);

  if (slide_offset < 0) {
    SBError sb_error;
    sb_error.SetErrorStringWithFormat("slide must be positive");
    return sb_error;
  }

  return SetModuleLoadAddress(module, static_cast<uint64_t>(slide_offset));
}

SBError SBTarget::SetModuleLoadAddress(lldb::SBModule module,
                                               uint64_t slide_offset) {

  SBError sb_error;

  if (TargetSP target_sp = GetSP()) {
    ModuleSP module_sp(module.GetSP());
    if (module_sp) {
      bool changed = false;
      if (module_sp->SetLoadAddress(*target_sp, slide_offset, true, changed)) {
        // The load was successful, make sure that at least some sections
        // changed before we notify that our module was loaded.
        if (changed) {
          ModuleList module_list;
          module_list.Append(module_sp);
          target_sp->ModulesDidLoad(module_list);
          // Flush info in the process (stack frames, etc)
          ProcessSP process_sp(target_sp->GetProcessSP());
          if (process_sp)
            process_sp->Flush();
        }
      }
    } else {
      sb_error.SetErrorStringWithFormat("invalid module");
    }

  } else {
    sb_error.SetErrorStringWithFormat("invalid target");
  }
  return sb_error;
}

SBError SBTarget::ClearModuleLoadAddress(lldb::SBModule module) {
  LLDB_INSTRUMENT_VA(this, module);

  SBError sb_error;

  char path[PATH_MAX];
  if (TargetSP target_sp = GetSP()) {
    ModuleSP module_sp(module.GetSP());
    if (module_sp) {
      ObjectFile *objfile = module_sp->GetObjectFile();
      if (objfile) {
        SectionList *section_list = objfile->GetSectionList();
        if (section_list) {
          ProcessSP process_sp(target_sp->GetProcessSP());

          bool changed = false;
          const size_t num_sections = section_list->GetSize();
          for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
            SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
            if (section_sp)
              changed |= target_sp->SetSectionUnloaded(section_sp);
          }
          if (changed) {
            ModuleList module_list;
            module_list.Append(module_sp);
            target_sp->ModulesDidUnload(module_list, false);
            // Flush info in the process (stack frames, etc)
            ProcessSP process_sp(target_sp->GetProcessSP());
            if (process_sp)
              process_sp->Flush();
          }
        } else {
          module_sp->GetFileSpec().GetPath(path, sizeof(path));
          sb_error.SetErrorStringWithFormat("no sections in object file '%s'",
                                            path);
        }
      } else {
        module_sp->GetFileSpec().GetPath(path, sizeof(path));
        sb_error.SetErrorStringWithFormat("no object file for module '%s'",
                                          path);
      }
    } else {
      sb_error.SetErrorStringWithFormat("invalid module");
    }
  } else {
    sb_error.SetErrorStringWithFormat("invalid target");
  }
  return sb_error;
}

lldb::SBSymbolContextList SBTarget::FindSymbols(const char *name,
                                                lldb::SymbolType symbol_type) {
  LLDB_INSTRUMENT_VA(this, name, symbol_type);

  SBSymbolContextList sb_sc_list;
  if (name && name[0]) {
    if (TargetSP target_sp = GetSP()) {
      target_sp->GetImages().FindSymbolsWithNameAndType(
          ConstString(name), symbol_type, *sb_sc_list);
    }
  }
  return sb_sc_list;
}

lldb::SBValue SBTarget::EvaluateExpression(const char *expr) {
  LLDB_INSTRUMENT_VA(this, expr);

  if (TargetSP target_sp = GetSP()) {
    SBExpressionOptions options;
    lldb::DynamicValueType fetch_dynamic_value =
        target_sp->GetPreferDynamicValue();
    options.SetFetchDynamicValue(fetch_dynamic_value);
    options.SetUnwindOnError(true);
    return EvaluateExpression(expr, options);
  }
  return SBValue();
}

lldb::SBValue SBTarget::EvaluateExpression(const char *expr,
                                           const SBExpressionOptions &options) {
  LLDB_INSTRUMENT_VA(this, expr, options);

  Log *expr_log = GetLog(LLDBLog::Expressions);
  SBValue expr_result;
  ValueObjectSP expr_value_sp;
  if (TargetSP target_sp = GetSP()) {
    StackFrame *frame = nullptr;
    if (expr == nullptr || expr[0] == '\0')
      return expr_result;

    TargetAPIMutex api_lock = target_sp->GetAPIMutex();
    std::lock_guard<TargetAPIMutex> guard(api_lock);
    ExecutionContext exe_ctx(m_opaque_sp.get());

    frame = exe_ctx.GetFramePtr();
    Target *target = exe_ctx.GetTargetPtr();
    Process *process = exe_ctx.GetProcessPtr();

    if (target) {
      // If we have a process, make sure to lock the runlock:
      if (process) {
        Process::StopLocker stop_locker;
        if (stop_locker.TryLock(&process->GetRunLock())) {
          target->EvaluateExpression(expr, frame, expr_value_sp, options.ref());
        } else {
          Status error;
          error = Status::FromErrorString("can't evaluate expressions when the "
                                          "process is running.");
          expr_value_sp =
              ValueObjectConstResult::Create(nullptr, std::move(error));
        }
      } else {
        target->EvaluateExpression(expr, frame, expr_value_sp, options.ref());
      }

      expr_result.SetSP(expr_value_sp, options.GetFetchDynamicValue());
    }
  }
  LLDB_LOGF(expr_log,
            "** [SBTarget::EvaluateExpression] Expression result is "
            "%s, summary %s **",
            expr_result.GetValue(), expr_result.GetSummary());
  return expr_result;
}

lldb::addr_t SBTarget::GetStackRedZoneSize() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP()) {
    ABISP abi_sp;
    ProcessSP process_sp(target_sp->GetProcessSP());
    if (process_sp)
      abi_sp = process_sp->GetABI();
    else
      abi_sp = ABI::FindPlugin(ProcessSP(), target_sp->GetArchitecture());
    if (abi_sp)
      return abi_sp->GetRedZoneSize();
  }
  return 0;
}

bool SBTarget::IsLoaded(const SBModule &module) const {
  LLDB_INSTRUMENT_VA(this, module);

  if (TargetSP target_sp = GetSP()) {
    ModuleSP module_sp(module.GetSP());
    if (module_sp)
      return module_sp->IsLoadedInTarget(target_sp.get());
  }
  return false;
}

lldb::SBLaunchInfo SBTarget::GetLaunchInfo() const {
  LLDB_INSTRUMENT_VA(this);

  lldb::SBLaunchInfo launch_info(nullptr);
  if (TargetSP target_sp = GetSP())
    launch_info.set_ref(m_opaque_sp->GetProcessLaunchInfo());
  return launch_info;
}

void SBTarget::SetLaunchInfo(const lldb::SBLaunchInfo &launch_info) {
  LLDB_INSTRUMENT_VA(this, launch_info);

  if (TargetSP target_sp = GetSP())
    m_opaque_sp->SetProcessLaunchInfo(launch_info.ref());
}

SBEnvironment SBTarget::GetEnvironment() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return SBEnvironment(target_sp->GetEnvironment());

  return SBEnvironment();
}

lldb::SBTrace SBTarget::GetTrace() {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return SBTrace(target_sp->GetTrace());

  return SBTrace();
}

lldb::SBTrace SBTarget::CreateTrace(lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, error);

  error.Clear();
  if (TargetSP target_sp = GetSP()) {
    if (llvm::Expected<lldb::TraceSP> trace_sp = target_sp->CreateTrace()) {
      return SBTrace(*trace_sp);
    } else {
      error.SetErrorString(llvm::toString(trace_sp.takeError()).c_str());
    }
  } else {
    error.SetErrorString("missing target");
  }
  return SBTrace();
}

lldb::SBMutex SBTarget::GetAPIMutex() const {
  LLDB_INSTRUMENT_VA(this);

  if (TargetSP target_sp = GetSP())
    return lldb::SBMutex(target_sp);
  return lldb::SBMutex();
}

uint32_t
SBTarget::RegisterScriptedFrameProvider(const char *class_name,
                                        lldb::SBStructuredData args_dict,
                                        lldb::SBError &error) {
  LLDB_INSTRUMENT_VA(this, class_name, args_dict, error);

  TargetSP target_sp = GetSP();
  if (!target_sp) {
    error.SetErrorString("invalid target");
    return 0;
  }

  if (!class_name || !class_name[0]) {
    error.SetErrorString("invalid class name");
    return 0;
  }

  // Extract the dictionary from SBStructuredData.
  StructuredData::DictionarySP dict_sp;
  if (args_dict.IsValid() && args_dict.m_impl_up) {
    StructuredData::ObjectSP obj_sp = args_dict.m_impl_up->GetObjectSP();
    if (obj_sp && obj_sp->GetType() != lldb::eStructuredDataTypeDictionary) {
      error.SetErrorString("SBStructuredData argument isn't a dictionary");
      return 0;
    }
    dict_sp = std::make_shared<StructuredData::Dictionary>(obj_sp);
  }

  // Create the ScriptedMetadata.
  ScriptedMetadataSP metadata_sp =
      std::make_shared<ScriptedMetadata>(class_name, dict_sp);

  // Create the interface for calling static methods.
  ScriptedFrameProviderInterfaceSP interface_sp =
      target_sp->GetDebugger()
          .GetScriptInterpreter()
          ->CreateScriptedFrameProviderInterface();

  // Create a descriptor (applies to all threads by default).
  ScriptedFrameProviderDescriptor descriptor(metadata_sp);
  descriptor.interface_sp = interface_sp;

  llvm::Expected<uint32_t> descriptor_id_or_err =
      target_sp->AddScriptedFrameProviderDescriptor(descriptor);
  if (!descriptor_id_or_err) {
    error.SetErrorString(
        llvm::toString(descriptor_id_or_err.takeError()).c_str());
    return 0;
  }

  // Register the descriptor with the target.
  return *descriptor_id_or_err;
}

lldb::SBError SBTarget::RemoveScriptedFrameProvider(uint32_t provider_id) {
  LLDB_INSTRUMENT_VA(this, provider_id);

  SBError error;
  TargetSP target_sp = GetSP();
  if (!target_sp) {
    error.SetErrorString("invalid target");
    return error;
  }

  if (!provider_id) {
    error.SetErrorString("invalid provider id");
    return error;
  }

  if (!target_sp->RemoveScriptedFrameProviderDescriptor(provider_id)) {
    error.SetErrorStringWithFormat("no frame provider named '%u' found",
                                   provider_id);
    return error;
  }

  return {};
}
