//===-- TargetList.cpp ------------------------------------------*- C++ -*-===//
//
// 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;

ConstString &TargetList::GetStaticBroadcasterClass() {
  static ConstString class_name("lldb.targetList");
  return class_name;
}

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

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
TargetList::~TargetList() {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  m_target_list.clear();
}

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) {
  return CreateTargetInternal(debugger, user_exe_path, triple_str,
                              load_dependent_files, platform_options, target_sp,
                              false);
}

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

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,
    bool is_dummy_target) {
  Status error;
  PlatformSP platform_sp;

  // This is purposely left empty unless it is specified by triple_cstr. If not
  // initialized via triple_cstr, then the currently selected platform will set
  // the architecture correctly.
  const ArchSpec arch(triple_str);
  if (!triple_str.empty()) {
    if (!arch.IsValid()) {
      error.SetErrorStringWithFormat("invalid triple '%s'",
                                     triple_str.str().c_str());
      return error;
    }
  }

  ArchSpec platform_arch(arch);

  bool prefer_platform_arch = false;

  CommandInterpreter &interpreter = debugger.GetCommandInterpreter();

  // let's see if there is already an existing platform before we go creating
  // another...
  platform_sp = debugger.GetPlatformList().GetSelectedPlatform();

  if (platform_options && platform_options->PlatformWasSpecified()) {
    // Create a new platform if it doesn't match the selected platform
    if (!platform_options->PlatformMatches(platform_sp)) {
      const bool select_platform = true;
      platform_sp = platform_options->CreatePlatformWithOptions(
          interpreter, arch, select_platform, error, platform_arch);
      if (!platform_sp)
        return error;
    }
  }

  if (!user_exe_path.empty()) {
    ModuleSpecList module_specs;
    ModuleSpec module_spec;
    module_spec.GetFileSpec().SetFile(user_exe_path, FileSpec::Style::native);
    FileSystem::Instance().Resolve(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;
    const size_t num_specs = ObjectFile::GetModuleSpecifications(
        module_spec.GetFileSpec(), file_offset, file_size, module_specs);
    if (num_specs > 0) {
      ModuleSpec matching_module_spec;

      if (num_specs == 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
              if (!platform_arch.TripleOSWasSpecified() ||
                  !platform_arch.TripleVendorWasSpecified()) {
                prefer_platform_arch = true;
                platform_arch = matching_module_spec.GetArchitecture();
              }
            } else {
              StreamString platform_arch_strm;
              StreamString module_arch_strm;

              platform_arch.DumpTriple(platform_arch_strm);
              matching_module_spec.GetArchitecture().DumpTriple(
                  module_arch_strm);
              error.SetErrorStringWithFormat(
                  "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()) {
          module_spec.GetArchitecture() = arch;
          if (module_specs.FindMatchingModuleSpec(module_spec,
                                                  matching_module_spec)) {
            prefer_platform_arch = true;
            platform_arch = matching_module_spec.GetArchitecture();
          }
        } else {
          // No architecture specified, check if there is only one platform for
          // all of the architectures.

          typedef std::vector<PlatformSP> PlatformList;
          PlatformList platforms;
          PlatformSP host_platform_sp = Platform::GetHostPlatform();
          for (size_t i = 0; i < num_specs; ++i) {
            ModuleSpec module_spec;
            if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
              // See if there was a selected platform and check that first
              // since the user may have specified it.
              if (platform_sp) {
                if (platform_sp->IsCompatibleArchitecture(
                        module_spec.GetArchitecture(), false, nullptr)) {
                  platforms.push_back(platform_sp);
                  continue;
                }
              }

              // Next check the host platform it if wasn't already checked
              // above
              if (host_platform_sp &&
                  (!platform_sp ||
                   host_platform_sp->GetName() != platform_sp->GetName())) {
                if (host_platform_sp->IsCompatibleArchitecture(
                        module_spec.GetArchitecture(), false, nullptr)) {
                  platforms.push_back(host_platform_sp);
                  continue;
                }
              }

              // Just find a platform that matches the architecture in the
              // executable file
              PlatformSP fallback_platform_sp(
                  Platform::GetPlatformForArchitecture(
                      module_spec.GetArchitecture(), nullptr));
              if (fallback_platform_sp) {
                platforms.push_back(fallback_platform_sp);
              }
            }
          }

          Platform *platform_ptr = nullptr;
          bool more_than_one_platforms = false;
          for (const auto &the_platform_sp : platforms) {
            if (platform_ptr) {
              if (platform_ptr->GetName() != the_platform_sp->GetName()) {
                more_than_one_platforms = true;
                platform_ptr = nullptr;
                break;
              }
            } else {
              platform_ptr = the_platform_sp.get();
            }
          }

          if (platform_ptr) {
            // All platforms for all modules in the executable match, so we can
            // select this platform
            platform_sp = platforms.front();
          } else if (!more_than_one_platforms) {
            // No platforms claim to support this file
            error.SetErrorString("No matching platforms found for this file, "
                                 "specify one with the --platform option");
            return error;
          } else {
            // More than one platform claims to support this file, so the
            // --platform option must be specified
            StreamString error_strm;
            std::set<Platform *> platform_set;
            error_strm.Printf(
                "more than one platform supports this executable (");
            for (const auto &the_platform_sp : platforms) {
              if (platform_set.find(the_platform_sp.get()) ==
                  platform_set.end()) {
                if (!platform_set.empty())
                  error_strm.PutCString(", ");
                error_strm.PutCString(the_platform_sp->GetName().GetCString());
                platform_set.insert(the_platform_sp.get());
              }
            }
            error_strm.Printf(
                "), use the --platform option to specify a platform");
            error.SetErrorString(error_strm.GetString());
            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, false, &platform_arch)) {
      platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
      if (!is_dummy_target && platform_sp)
        debugger.GetPlatformList().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, false,
                                               &fixed_platform_arch)) {
      platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
                                                         &fixed_platform_arch);
      if (!is_dummy_target && platform_sp)
        debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
    }
  }

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

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

lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
  // FIXME: Maybe the dummy target should be per-Debugger
  if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
    ArchSpec arch(Target::GetDefaultArchitecture());
    if (!arch.IsValid())
      arch = HostInfo::GetArchitecture();
    Status err = CreateDummyTarget(
        debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
  }

  return m_dummy_target_sp;
}

Status TargetList::CreateDummyTarget(Debugger &debugger,
                                     llvm::StringRef specified_arch_name,
                                     lldb::TargetSP &target_sp) {
  PlatformSP host_platform_sp(Platform::GetHostPlatform());
  return CreateTargetInternal(
      debugger, (const char *)nullptr, specified_arch_name, eLoadDependentsNo,
      (const OptionGroupPlatform *)nullptr, target_sp, true);
}

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,
                                        bool is_dummy_target) {
  static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
  Timer scoped_timer(
      func_cat, "TargetList::CreateTarget (file = '%s', arch = '%s')",
      user_exe_path.str().c_str(), specified_arch.GetArchitectureName());
  Status error;

  ArchSpec arch(specified_arch);

  if (arch.IsValid()) {
    if (!platform_sp ||
        !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
      platform_sp = Platform::GetPlatformForArchitecture(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.startswith("~")) {
    // 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) {
      FileSpecList executable_search_paths(
          Target::GetDefaultExecutableSearchPaths());
      ModuleSpec module_spec(file, arch);
      error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
                                             executable_search_paths.GetSize()
                                                 ? &executable_search_paths
                                                 : nullptr);
    }

    if (error.Success() && exe_module_sp) {
      if (exe_module_sp->GetObjectFile() == nullptr) {
        if (arch.IsValid()) {
          error.SetErrorStringWithFormat(
              "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
              arch.GetArchitectureName());
        } else {
          error.SetErrorStringWithFormat("unsupported file type \"%s\"",
                                         file.GetPath().c_str());
        }
        return error;
      }
      target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
      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));
    }
  } 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));
  }

  if (target_sp) {
    // 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.GetDirectory() = file.GetDirectory();
      target_sp->GetExecutableSearchPaths().Append(file_dir);
    }

    // Don't put the dummy target in the target list, it's held separately.
    if (!is_dummy_target) {
      std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
      m_selected_target_idx = m_target_list.size();
      m_target_list.push_back(target_sp);
      // Now prime this from the dummy target:
      target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
    } else {
      m_dummy_target_sp = target_sp;
    }
  }

  return error;
}

bool TargetList::DeleteTarget(TargetSP &target_sp) {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  collection::iterator pos, end = m_target_list.end();

  for (pos = m_target_list.begin(); pos != end; ++pos) {
    if (pos->get() == target_sp.get()) {
      m_target_list.erase(pos);
      return true;
    }
  }
  return false;
}

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);
  TargetSP target_sp;
  bool full_match = (bool)exe_file_spec.GetDirectory();

  collection::const_iterator pos, end = m_target_list.end();
  for (pos = m_target_list.begin(); pos != end; ++pos) {
    Module *exe_module = (*pos)->GetExecutableModulePointer();

    if (exe_module) {
      if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
                          full_match)) {
        if (exe_arch_ptr) {
          if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
            continue;
        }
        target_sp = *pos;
        break;
      }
    }
  }
  return target_sp;
}

TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  TargetSP target_sp;
  collection::const_iterator pos, end = m_target_list.end();
  for (pos = m_target_list.begin(); pos != end; ++pos) {
    Process *process = (*pos)->GetProcessSP().get();
    if (process && process->GetID() == pid) {
      target_sp = *pos;
      break;
    }
  }
  return target_sp;
}

TargetSP TargetList::FindTargetWithProcess(Process *process) const {
  TargetSP target_sp;
  if (process) {
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    collection::const_iterator pos, end = m_target_list.end();
    for (pos = m_target_list.begin(); pos != end; ++pos) {
      if (process == (*pos)->GetProcessSP().get()) {
        target_sp = *pos;
        break;
      }
    }
  }
  return target_sp;
}

TargetSP TargetList::GetTargetSP(Target *target) const {
  TargetSP target_sp;
  if (target) {
    std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
    collection::const_iterator pos, end = m_target_list.end();
    for (pos = m_target_list.begin(); pos != end; ++pos) {
      if (target == (*pos).get()) {
        target_sp = *pos;
        break;
      }
    }
  }
  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);
    collection::iterator pos, end = m_target_list.end();
    for (pos = m_target_list.begin(); pos != end; ++pos) {
      process = (*pos)->GetProcessSP().get();
      if (process) {
        if (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) {
        if (process->IsAlive()) {
          ++num_signals_sent;
          process->Signal(signo);
        }
      }
    }
  }
  return num_signals_sent;
}

int 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);
  size_t num_targets = m_target_list.size();
  for (size_t idx = 0; idx < num_targets; idx++) {
    if (target_sp == m_target_list[idx])
      return idx;
  }
  return UINT32_MAX;
}

uint32_t TargetList::SetSelectedTarget(Target *target) {
  std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
  collection::const_iterator pos, begin = m_target_list.begin(),
                                  end = m_target_list.end();
  for (pos = begin; pos != end; ++pos) {
    if (pos->get() == target) {
      m_selected_target_idx = std::distance(begin, pos);
      return m_selected_target_idx;
    }
  }
  m_selected_target_idx = 0;
  return m_selected_target_idx;
}

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