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

// C Includes
// C++ Includes
// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"

// Project includes
#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/Core/Timer.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/Target/TargetList.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();
}

Error
TargetList::CreateTarget (Debugger &debugger,
                          const char *user_exe_path,
                          const char *triple_cstr,
                          bool get_dependent_files,
                          const OptionGroupPlatform *platform_options,
                          TargetSP &target_sp)
{
    return CreateTargetInternal (debugger,
                                 user_exe_path,
                                 triple_cstr,
                                 get_dependent_files,
                                 platform_options,
                                 target_sp,
                                 false);
}

Error
TargetList::CreateTarget (Debugger &debugger,
                          const char *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);
}

Error
TargetList::CreateTargetInternal (Debugger &debugger,
                                  const char *user_exe_path,
                                  const char *triple_cstr,
                                  bool get_dependent_files,
                                  const OptionGroupPlatform *platform_options,
                                  TargetSP &target_sp,
                                  bool is_dummy_target)
{
    Error 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_cstr);
    if (triple_cstr && triple_cstr[0])
    {
        if (!arch.IsValid())
        {
            error.SetErrorStringWithFormat("invalid triple '%s'", triple_cstr);
            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 && user_exe_path[0])
    {
        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.GetString().c_str(),
                                                           module_arch_strm.GetString().c_str(),
                                                           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().c_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, 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();
        Error err = CreateDummyTarget(debugger,
                                      arch.GetTriple().getTriple().c_str(),
                                      m_dummy_target_sp);
    }

    return m_dummy_target_sp;
}

Error
TargetList::CreateDummyTarget (Debugger &debugger,
                               const char *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);
}

Error
TargetList::CreateTargetInternal (Debugger &debugger,
                                  const char *user_exe_path,
                                  const ArchSpec& specified_arch,
                                  bool get_dependent_files,
                                  lldb::PlatformSP &platform_sp,
                                  lldb::TargetSP &target_sp,
                                  bool is_dummy_target)
{
    Timer scoped_timer (__PRETTY_FUNCTION__,
                        "TargetList::CreateTarget (file = '%s', arch = '%s')",
                        user_exe_path,
                        specified_arch.GetArchitectureName());
    Error 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 && user_exe_path[0] == '~')
    {
        // 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(user_exe_path);
        FileSpec::ResolveUsername(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 (file.GetFileType() == FileSpec::eFileTypeDirectory)
            user_exe_path_is_bundle = true;

        if (file.IsRelative() && user_exe_path)
        {
            // Ignore paths that start with "./" and "../"
            if (!((user_exe_path[0] == '.' && user_exe_path[1] == '/') ||
                  (user_exe_path[0] == '.' && user_exe_path[1] == '.' && user_exe_path[2] == '/')))
            {
                char cwd[PATH_MAX];
                if (getcwd (cwd, sizeof(cwd)))
                {
                    std::string cwd_user_exe_path (cwd);
                    cwd_user_exe_path += '/';
                    cwd_user_exe_path += user_exe_path;
                    FileSpec cwd_file (cwd_user_exe_path.c_str(), 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)
        {
            // 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);
}
