//===-- TargetList.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/Target/TargetList.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/OptionGroupPlatform.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "lldb/Utility/Timer.h"

#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"

using namespace lldb;
using namespace lldb_private;

llvm::StringRef TargetList::GetStaticBroadcasterClass() {
  static constexpr llvm::StringLiteral class_name("lldb.targetList");
  return class_name;
}

// TargetList constructor
TargetList::TargetList(Debugger &debugger)
    : Broadcaster(debugger.GetBroadcasterManager(),
                  TargetList::GetStaticBroadcasterClass().str()),
      m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
  CheckInWithManager();
}

Status TargetList::CreateTarget(Debugger &debugger,
                                llvm::StringRef user_exe_path,
                                llvm::StringRef triple_str,
                                LoadDependentFiles load_dependent_files,
                                const OptionGroupPlatform *platform_options,
                                TargetSP &target_sp) {

  auto result = TargetList::CreateTargetInternal(
      debugger, user_exe_path, triple_str, load_dependent_files,
      platform_options, target_sp);

  if (target_sp && result.Success())
    AddTargetInternal(target_sp, /*do_select*/ true);
  return result;
}

Status TargetList::CreateTarget(Debugger &debugger,
                                llvm::StringRef user_exe_path,
                                const ArchSpec &specified_arch,
                                LoadDependentFiles load_dependent_files,
                                PlatformSP &platform_sp, TargetSP &target_sp) {

  auto result = TargetList::CreateTargetInternal(
      debugger, user_exe_path, specified_arch, load_dependent_files,
      platform_sp, target_sp);

  if (target_sp && result.Success())
    AddTargetInternal(target_sp, /*do_select*/ true);
  return result;
}

Status TargetList::CreateTargetInternal(
    Debugger &debugger, llvm::StringRef user_exe_path,
    llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
    const OptionGroupPlatform *platform_options, TargetSP &target_sp) {
  Status error;

  PlatformList &platform_list = debugger.GetPlatformList();
  // Let's start by looking at the selected platform.
  PlatformSP platform_sp = platform_list.GetSelectedPlatform();

  // This variable corresponds to the architecture specified by the triple
  // string. If that string was empty the currently selected platform will
  // determine the architecture.
  const ArchSpec arch(triple_str);
  if (!triple_str.empty() && !arch.IsValid()) {
    error = Status::FromErrorStringWithFormat("invalid triple '%s'",
                                              triple_str.str().c_str());
    return error;
  }

  ArchSpec platform_arch(arch);

  // Create a new platform if a platform was specified in the platform options
  // and doesn't match the selected platform.
  if (platform_options && platform_options->PlatformWasSpecified() &&
      !platform_options->PlatformMatches(platform_sp)) {
    const bool select_platform = true;
    platform_sp = platform_options->CreatePlatformWithOptions(
        debugger.GetCommandInterpreter(), arch, select_platform, error,
        platform_arch);
    if (!platform_sp)
      return error;
  }

  bool prefer_platform_arch = false;
  auto update_platform_arch = [&](const ArchSpec &module_arch) {
    // If the OS or vendor weren't specified, then adopt the module's
    // architecture so that the platform matching can be more accurate.
    if (!platform_arch.TripleOSWasSpecified() ||
        !platform_arch.TripleVendorWasSpecified()) {
      prefer_platform_arch = true;
      platform_arch = module_arch;
    }
  };

  if (!user_exe_path.empty()) {
    ModuleSpec module_spec(FileSpec(user_exe_path, FileSpec::Style::native));
    FileSystem::Instance().Resolve(module_spec.GetFileSpec());

    // Try to resolve the exe based on PATH and/or platform-specific suffixes,
    // but only if using the host platform.
    if (platform_sp->IsHost() &&
        !FileSystem::Instance().Exists(module_spec.GetFileSpec()))
      FileSystem::Instance().ResolveExecutableLocation(
          module_spec.GetFileSpec());

    // Resolve the executable in case we are given a path to a application
    // bundle like a .app bundle on MacOSX.
    Host::ResolveExecutableInBundle(module_spec.GetFileSpec());

    lldb::offset_t file_offset = 0;
    lldb::offset_t file_size = 0;
    ModuleSpecList module_specs = ObjectFile::GetModuleSpecifications(
        module_spec.GetFileSpec(), file_offset, file_size);

    if (module_specs.GetSize() > 0) {
      ModuleSpec matching_module_spec;

      if (module_specs.GetSize() == 1) {
        if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
          if (platform_arch.IsValid()) {
            if (platform_arch.IsCompatibleMatch(
                    matching_module_spec.GetArchitecture())) {
              // If the OS or vendor weren't specified, then adopt the module's
              // architecture so that the platform matching can be more
              // accurate.
              update_platform_arch(matching_module_spec.GetArchitecture());
            } else {
              StreamString platform_arch_strm;
              StreamString module_arch_strm;

              platform_arch.DumpTriple(platform_arch_strm.AsRawOstream());
              matching_module_spec.GetArchitecture().DumpTriple(
                  module_arch_strm.AsRawOstream());
              error = Status::FromErrorStringWithFormat(
                  "the specified architecture '%s' is not compatible with '%s' "
                  "in '%s'",
                  platform_arch_strm.GetData(), module_arch_strm.GetData(),
                  module_spec.GetFileSpec().GetPath().c_str());
              return error;
            }
          } else {
            // Only one arch and none was specified.
            prefer_platform_arch = true;
            platform_arch = matching_module_spec.GetArchitecture();
          }
        }
      } else if (arch.IsValid()) {
        // Fat binary. A (valid) architecture was specified.
        module_spec.GetArchitecture() = arch;
        if (module_specs.FindMatchingModuleSpec(module_spec,
                                                matching_module_spec))
            update_platform_arch(matching_module_spec.GetArchitecture());
      } else {
        // Fat binary. No architecture specified, check if there is
        // only one platform for all of the architectures.
        std::vector<PlatformSP> candidates;
        std::vector<ArchSpec> archs;
        for (const ModuleSpec &spec : module_specs.ModuleSpecs())
          archs.push_back(spec.GetArchitecture());
        if (PlatformSP platform_for_archs_sp =
                platform_list.GetOrCreate(archs, {}, candidates)) {
          platform_sp = platform_for_archs_sp;
        } else if (candidates.empty()) {
          error = Status::FromErrorString(
              "no matching platforms found for this file");
          return error;
        } else {
          // More than one platform claims to support this file.
          StreamString error_strm;
          std::set<llvm::StringRef> platform_set;
          error_strm.Printf(
              "more than one platform supports this executable (");
          for (const auto &candidate : candidates) {
            llvm::StringRef platform_name = candidate->GetName();
            if (platform_set.count(platform_name))
              continue;
            if (!platform_set.empty())
              error_strm.PutCString(", ");
            error_strm.PutCString(platform_name);
            platform_set.insert(platform_name);
          }
          error_strm.Printf("), specify an architecture to disambiguate");
          error = Status(error_strm.GetString().str());
          return error;
        }
      }
    }
  }

  // If we have a valid architecture, make sure the current platform is
  // compatible with that architecture.
  if (!prefer_platform_arch && arch.IsValid()) {
    if (!platform_sp->IsCompatibleArchitecture(
            arch, {}, ArchSpec::CompatibleMatch, nullptr)) {
      platform_sp = platform_list.GetOrCreate(arch, {}, &platform_arch);
      if (platform_sp)
        platform_list.SetSelectedPlatform(platform_sp);
    }
  } else if (platform_arch.IsValid()) {
    // If "arch" isn't valid, yet "platform_arch" is, it means we have an
    // executable file with a single architecture which should be used.
    ArchSpec fixed_platform_arch;
    if (!platform_sp->IsCompatibleArchitecture(
            platform_arch, {}, ArchSpec::CompatibleMatch, nullptr)) {
      platform_sp =
          platform_list.GetOrCreate(platform_arch, {}, &fixed_platform_arch);
      if (platform_sp)
        platform_list.SetSelectedPlatform(platform_sp);
    }
  }

  if (!platform_arch.IsValid())
    platform_arch = arch;

  return TargetList::CreateTargetInternal(debugger, user_exe_path,
                                          platform_arch, load_dependent_files,
                                          platform_sp, target_sp);
}

Status TargetList::CreateTargetInternal(Debugger &debugger,
                                        llvm::StringRef user_exe_path,
                                        const ArchSpec &specified_arch,
                                        LoadDependentFiles load_dependent_files,
                                        lldb::PlatformSP &platform_sp,
                                        lldb::TargetSP &target_sp) {
  LLDB_SCOPED_TIMERF("TargetList::CreateTarget (file = '%s', arch = '%s')",
                     user_exe_path.str().c_str(),
                     specified_arch.GetArchitectureName());
  Status error;
  const bool is_dummy_target = false;

  ArchSpec arch(specified_arch);

  if (arch.IsValid()) {
    if (!platform_sp || !platform_sp->IsCompatibleArchitecture(
                            arch, {}, ArchSpec::CompatibleMatch, nullptr))
      platform_sp =
          debugger.GetPlatformList().GetOrCreate(specified_arch, {}, &arch);
  }

  if (!platform_sp)
    platform_sp = debugger.GetPlatformList().GetSelectedPlatform();

  if (!arch.IsValid())
    arch = specified_arch;

  FileSpec file(user_exe_path);
  if (!FileSystem::Instance().Exists(file) && user_exe_path.starts_with("~")) {
    // we want to expand the tilde but we don't want to resolve any symbolic
    // links so we can't use the FileSpec constructor's resolve flag
    llvm::SmallString<64> unglobbed_path;
    StandardTildeExpressionResolver Resolver;
    Resolver.ResolveFullPath(user_exe_path, unglobbed_path);

    if (unglobbed_path.empty())
      file = FileSpec(user_exe_path);
    else
      file = FileSpec(unglobbed_path.c_str());
  }

  bool user_exe_path_is_bundle = false;
  char resolved_bundle_exe_path[PATH_MAX];
  resolved_bundle_exe_path[0] = '\0';
  if (file) {
    if (FileSystem::Instance().IsDirectory(file))
      user_exe_path_is_bundle = true;

    if (file.IsRelative() && !user_exe_path.empty()) {
      llvm::SmallString<64> cwd;
      if (! llvm::sys::fs::current_path(cwd)) {
        FileSpec cwd_file(cwd.c_str());
        cwd_file.AppendPathComponent(file);
        if (FileSystem::Instance().Exists(cwd_file))
          file = cwd_file;
      }
    }

    ModuleSP exe_module_sp;
    if (platform_sp) {
      ModuleSpec module_spec(file, arch);
      module_spec.SetTarget(target_sp);
      // Set the platform so that GetSharedModule can use it for the locate
      // module callback, even when Target is not yet available (during target
      // creation for launch mode).
      module_spec.SetPlatform(platform_sp);
      error = platform_sp->ResolveExecutable(module_spec, exe_module_sp);
    }

    if (error.Success() && exe_module_sp) {
      if (exe_module_sp->GetObjectFile() == nullptr) {
        if (arch.IsValid()) {
          error = Status::FromErrorStringWithFormat(
              "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
              arch.GetArchitectureName());
        } else {
          error = Status::FromErrorStringWithFormat(
              "unsupported file type \"%s\"", file.GetPath().c_str());
        }
        return error;
      }
      target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
      debugger.GetTargetList().RegisterInProcessTarget(target_sp);
      target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
      if (user_exe_path_is_bundle)
        exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
                                             sizeof(resolved_bundle_exe_path));
      if (target_sp->GetPreloadSymbols())
        exe_module_sp->PreloadSymbols();
    }
  } else {
    // No file was specified, just create an empty target with any arch if a
    // valid arch was specified
    target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
    debugger.GetTargetList().RegisterInProcessTarget(target_sp);
  }

  if (!target_sp)
    return error;

  // Set argv0 with what the user typed, unless the user specified a
  // directory. If the user specified a directory, then it is probably a
  // bundle that was resolved and we need to use the resolved bundle path
  if (!user_exe_path.empty()) {
    // Use exactly what the user typed as the first argument when we exec or
    // posix_spawn
    if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
      target_sp->SetArg0(resolved_bundle_exe_path);
    } else {
      // Use resolved path
      target_sp->SetArg0(file.GetPath().c_str());
    }
  }
  if (file.GetDirectory()) {
    FileSpec file_dir;
    file_dir.SetDirectory(file.GetDirectory());
    target_sp->AppendExecutableSearchPaths(file_dir);
  }

  // Now prime this from the dummy target:
  target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());

  return error;
}

bool TargetList::DeleteTarget(TargetSP &target_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find(m_target_list, target_sp);
  if (it == m_target_list.end())
    return false;

  m_target_list.erase(it);
  return true;
}

TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
    const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find_if(
      m_target_list, [&exe_file_spec, exe_arch_ptr](const TargetSP &item) {
        Module *exe_module = item->GetExecutableModulePointer();
        if (!exe_module ||
            !FileSpec::Match(exe_file_spec, exe_module->GetFileSpec()))
          return false;

        return !exe_arch_ptr ||
               exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture());
      });

  if (it != m_target_list.end())
    return *it;

  return TargetSP();
}

TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find_if(m_target_list, [pid](const TargetSP &item) {
    auto *process_ptr = item->GetProcessSP().get();
    return process_ptr && (process_ptr->GetID() == pid);
  });

  if (it != m_target_list.end())
    return *it;

  return TargetSP();
}

TargetSP TargetList::FindTargetWithProcess(Process *process) const {
  TargetSP target_sp;
  if (!process)
    return target_sp;

  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find_if(m_target_list, [process](const TargetSP &item) {
    return item->GetProcessSP().get() == process;
  });

  if (it != m_target_list.end())
    target_sp = *it;

  return target_sp;
}

TargetSP TargetList::FindTargetByGloballyUniqueID(lldb::user_id_t id) const {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find_if(m_target_list, [id](const TargetSP &item) {
    return item->GetGloballyUniqueID() == id;
  });

  if (it != m_target_list.end())
    return *it;

  return TargetSP();
}

TargetSP TargetList::GetTargetSP(Target *target) const {
  TargetSP target_sp;
  if (!target)
    return target_sp;

  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find_if(m_target_list, [target](const TargetSP &item) {
    return item.get() == target;
  });
  if (it != m_target_list.end())
    target_sp = *it;

  return target_sp;
}

uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
  uint32_t num_async_interrupts_sent = 0;

  if (pid != LLDB_INVALID_PROCESS_ID) {
    TargetSP target_sp(FindTargetWithProcessID(pid));
    if (target_sp) {
      Process *process = target_sp->GetProcessSP().get();
      if (process) {
        process->SendAsyncInterrupt();
        ++num_async_interrupts_sent;
      }
    }
  } else {
    // We don't have a valid pid to broadcast to, so broadcast to the target
    // list's async broadcaster...
    BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
  }

  return num_async_interrupts_sent;
}

uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
  uint32_t num_signals_sent = 0;
  Process *process = nullptr;
  if (pid == LLDB_INVALID_PROCESS_ID) {
    // Signal all processes with signal
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    for (const auto &target_sp : m_target_list) {
      process = target_sp->GetProcessSP().get();
      if (process && process->IsAlive()) {
        ++num_signals_sent;
        process->Signal(signo);
      }
    }
  } else {
    // Signal a specific process with signal
    TargetSP target_sp(FindTargetWithProcessID(pid));
    if (target_sp) {
      process = target_sp->GetProcessSP().get();
      if (process && process->IsAlive()) {
        ++num_signals_sent;
        process->Signal(signo);
      }
    }
  }
  return num_signals_sent;
}

size_t TargetList::GetNumTargets() const {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  return m_target_list.size();
}

lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
  TargetSP target_sp;
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  if (idx < m_target_list.size())
    target_sp = m_target_list[idx];
  return target_sp;
}

uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  auto it = llvm::find(m_target_list, target_sp);
  if (it != m_target_list.end())
    return std::distance(m_target_list.begin(), it);
  return UINT32_MAX;
}

void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  lldbassert(!llvm::is_contained(m_target_list, target_sp) &&
             "target already exists it the list");
  UnregisterInProcessTarget(target_sp);
  m_target_list.push_back(std::move(target_sp));
  if (do_select)
    SetSelectedTargetInternal(m_target_list.size() - 1);
}

void TargetList::SetSelectedTargetInternal(uint32_t index) {
  lldbassert(!m_target_list.empty());
  m_selected_target_idx = index < m_target_list.size() ? index : 0;
}

void TargetList::SetSelectedTarget(uint32_t index) {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  SetSelectedTargetInternal(index);
}

void TargetList::SetSelectedTarget(const TargetSP &target_sp) {
  // Don't allow an invalid target shared pointer or a target that has been
  // destroyed to become the selected target.
  if (target_sp && target_sp->IsValid()) {
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    auto it = llvm::find(m_target_list, target_sp);
    SetSelectedTargetInternal(std::distance(m_target_list.begin(), it));
  }
}

lldb::TargetSP TargetList::GetSelectedTarget() {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  if (m_selected_target_idx >= m_target_list.size())
    m_selected_target_idx = 0;
  return GetTargetAtIndex(m_selected_target_idx);
}

bool TargetList::AnyTargetContainsModule(Module &module) {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  for (const auto &target_sp : m_target_list) {
    if (target_sp->GetImages().FindModule(&module))
      return true;
  }
  for (const auto &target_sp: m_in_process_target_list) {
    if (target_sp->GetImages().FindModule(&module))
      return true;
  }
  return false;
}

  void TargetList::RegisterInProcessTarget(TargetSP target_sp) {
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    [[maybe_unused]] bool was_added;
    std::tie(std::ignore, was_added) =
        m_in_process_target_list.insert(target_sp);
    assert(was_added && "Target pointer was left in the in-process map");
  }
  
  void TargetList::UnregisterInProcessTarget(TargetSP target_sp) {
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    [[maybe_unused]] bool was_present =
        m_in_process_target_list.erase(target_sp);
    assert(was_present && "Target pointer being removed was not registered");
  }
  
  bool TargetList::IsTargetInProcess(TargetSP target_sp) {
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    return m_in_process_target_list.count(target_sp) == 1; 
  }
