//===-- 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/Core/State.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/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 plaform 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);

    // 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 exectuable 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()) {
      // Ignore paths that start with "./" and "../"
      if (!user_exe_path.startswith("./") && !user_exe_path.startswith("../")) {
        llvm::SmallString<64> cwd;
        if (! llvm::sys::fs::current_path(cwd)) {
          cwd += '/';
          cwd += user_exe_path;
          FileSpec cwd_file(cwd, false);
          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);
}
