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

// Project includes
#include "lldb/Target/TargetList.h"
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Event.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/State.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "lldb/Utility/Timer.h"

// Other libraries and framework includes
#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,
                                bool get_dependent_files,
                                const OptionGroupPlatform *platform_options,
                                TargetSP &target_sp) {
  return CreateTargetInternal(debugger, user_exe_path, triple_str,
                              get_dependent_files, platform_options, target_sp,
                              false);
}

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

Status TargetList::CreateTargetInternal(
    Debugger &debugger, llvm::StringRef user_exe_path,
    llvm::StringRef triple_str, bool get_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, true,
                                      FileSpec::Style::native);

    // 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 == false) {
            // 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, get_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, false,
      (const OptionGroupPlatform *)nullptr, target_sp, true);
}

Status TargetList::CreateTargetInternal(Debugger &debugger,
                                        llvm::StringRef user_exe_path,
                                        const ArchSpec &specified_arch,
                                        bool get_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, false);
  if (!file.Exists() && 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, false);
    else
      file = FileSpec(unglobbed_path.c_str(), false);
  }

  bool user_exe_path_is_bundle = false;
  char resolved_bundle_exe_path[PATH_MAX];
  resolved_bundle_exe_path[0] = '\0';
  if (file) {
    if (llvm::sys::fs::is_directory(file.GetPath()))
      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(), false);
        cwd_file.AppendPathComponent(file);
        if (cwd_file.Exists())
          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, get_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);
}
