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

// Windows includes
#include "lldb/Host/windows/windows.h"

// C++ Includes
#include <list>
#include <vector>

// Other libraries and framework includes
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/HostNativeProcessBase.h"
#include "lldb/Host/HostNativeThreadBase.h"
#include "lldb/Host/MonitoringProcessLauncher.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/ProcessLauncherWindows.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"

#include "DebuggerThread.h"
#include "ExceptionRecord.h"
#include "LocalDebugDelegate.h"
#include "ProcessWindows.h"
#include "TargetThreadWindows.h"

#include "llvm/Support/raw_ostream.h"

using namespace lldb;
using namespace lldb_private;

namespace lldb_private
{

// We store a pointer to this class in the ProcessWindows, so that we don't expose Windows
// OS specific types and implementation details from a public header file.
class ProcessWindowsData
{
  public:
    ProcessWindowsData(const ProcessLaunchInfo &launch_info)
        : m_initial_stop_event(nullptr)
        , m_launch_info(launch_info)
        , m_initial_stop_received(false)
    {
        m_initial_stop_event = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
    }

    ~ProcessWindowsData() { ::CloseHandle(m_initial_stop_event); }

    ProcessLaunchInfo m_launch_info;
    lldb_private::Error m_launch_error;
    lldb_private::DebuggerThreadSP m_debugger;
    StopInfoSP m_pending_stop_info;
    HANDLE m_initial_stop_event;
    bool m_initial_stop_received;
    std::map<lldb::tid_t, HostThread> m_new_threads;
    std::map<lldb::tid_t, HostThread> m_exited_threads;
};
}
//------------------------------------------------------------------------------
// Static functions.

ProcessSP
ProcessWindows::CreateInstance(Target &target, Listener &listener, const FileSpec *)
{
    return ProcessSP(new ProcessWindows(target, listener));
}

void
ProcessWindows::Initialize()
{
    static bool g_initialized = false;

    if (!g_initialized)
    {
        g_initialized = true;
        PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                      GetPluginDescriptionStatic(),
                                      CreateInstance);
    }
}

//------------------------------------------------------------------------------
// Constructors and destructors.

ProcessWindows::ProcessWindows(Target &target, Listener &listener)
    : lldb_private::Process(target, listener)
{
}

ProcessWindows::~ProcessWindows()
{
}

void
ProcessWindows::Terminate()
{
}

lldb_private::ConstString
ProcessWindows::GetPluginNameStatic()
{
    static ConstString g_name("windows");
    return g_name;
}

const char *
ProcessWindows::GetPluginDescriptionStatic()
{
    return "Process plugin for Windows";
}

size_t
ProcessWindows::GetSTDOUT(char *buf, size_t buf_size, Error &error)
{
    error.SetErrorString("GetSTDOUT unsupported on Windows");
    return 0;
}

size_t
ProcessWindows::GetSTDERR(char *buf, size_t buf_size, Error &error)
{
    error.SetErrorString("GetSTDERR unsupported on Windows");
    return 0;
}

size_t
ProcessWindows::PutSTDIN(const char *buf, size_t buf_size, Error &error)
{
    error.SetErrorString("PutSTDIN unsupported on Windows");
    return 0;
}

Error
ProcessWindows::EnableBreakpointSite(BreakpointSite *bp_site)
{
    return EnableSoftwareBreakpoint(bp_site);
}

Error
ProcessWindows::DisableBreakpointSite(BreakpointSite *bp_site)
{
    return DisableSoftwareBreakpoint(bp_site);
}

bool
ProcessWindows::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
    // Add all the threads that were previously running and for which we did not detect a thread
    // exited event.
    int new_size = 0;
    for (ThreadSP old_thread : old_thread_list.Threads())
    {
        lldb::tid_t old_thread_id = old_thread->GetID();
        auto exited_thread_iter = m_session_data->m_exited_threads.find(old_thread_id);
        if (exited_thread_iter == m_session_data->m_exited_threads.end())
        {
            new_thread_list.AddThread(old_thread);
            ++new_size;
        }
    }

    // Also add all the threads that are new since the last time we broke into the debugger.
    for (auto iter = m_session_data->m_new_threads.begin(); iter != m_session_data->m_new_threads.end(); ++iter)
    {
        ThreadSP thread(new TargetThreadWindows(*this, iter->second));
        thread->SetID(iter->first);
        new_thread_list.AddThread(thread);
        ++new_size;
    }

    m_session_data->m_new_threads.clear();
    m_session_data->m_exited_threads.clear();

    return new_size > 0;
}

Error
ProcessWindows::DoLaunch(Module *exe_module,
                         ProcessLaunchInfo &launch_info)
{
    // Even though m_session_data is accessed here, it is before a debugger thread has been
    // kicked off.  So there's no race conditions, and it shouldn't be necessary to acquire
    // the mutex.

    Error result;
    if (!launch_info.GetFlags().Test(eLaunchFlagDebug))
    {
        result.SetErrorString("ProcessWindows can only be used to launch processes for debugging.");
        return result;
    }

    m_session_data.reset(new ProcessWindowsData(launch_info));

    SetPrivateState(eStateLaunching);
    DebugDelegateSP delegate(new LocalDebugDelegate(shared_from_this()));
    m_session_data->m_debugger.reset(new DebuggerThread(delegate));
    DebuggerThreadSP debugger = m_session_data->m_debugger;

    // Kick off the DebugLaunch asynchronously and wait for it to complete.
    result = debugger->DebugLaunch(launch_info);

    HostProcess process;
    if (result.Success())
    {
        // Block this function until we receive the initial stop from the process.
        if (::WaitForSingleObject(m_session_data->m_initial_stop_event, INFINITE) == WAIT_OBJECT_0)
            process = debugger->GetProcess();
        else
            result.SetError(::GetLastError(), eErrorTypeWin32);
    }

    if (!result.Success())
        return result;

    // We've hit the initial stop.  The private state should already be set to stopped as a result
    // of encountering the breakpoint exception in ProcessWindows::OnDebugException.
    launch_info.SetProcessID(process.GetProcessId());
    SetID(process.GetProcessId());

    return result;
}

Error
ProcessWindows::DoResume()
{
    llvm::sys::ScopedLock lock(m_mutex);

    Error error;
    if (GetPrivateState() == eStateStopped || GetPrivateState() == eStateCrashed)
    {
        ExceptionRecordSP active_exception = m_session_data->m_debugger->GetActiveException().lock();
        if (active_exception)
        {
            // Resume the process and continue processing debug events.  Mask the exception so that
            // from the process's view, there is no indication that anything happened.
            m_session_data->m_debugger->ContinueAsyncException(ExceptionResult::MaskException);
        }

        SetPrivateState(eStateRunning);
    }
    return error;
}


//------------------------------------------------------------------------------
// ProcessInterface protocol.

lldb_private::ConstString
ProcessWindows::GetPluginName()
{
    return GetPluginNameStatic();
}

uint32_t
ProcessWindows::GetPluginVersion()
{
    return 1;
}

Error
ProcessWindows::DoDetach(bool keep_stopped)
{
    Error error;
    return error;
}

Error
ProcessWindows::DoDestroy()
{
    llvm::sys::ScopedLock lock(m_mutex);

    Error error;
    if (GetPrivateState() != eStateExited && GetPrivateState() != eStateDetached && m_session_data)
    {
        DebuggerThread &debugger = *m_session_data->m_debugger;
        error = debugger.StopDebugging(true);
    }
    m_session_data.reset();
    return error;
}

void
ProcessWindows::RefreshStateAfterStop()
{
    llvm::sys::ScopedLock lock(m_mutex);

    if (!m_session_data)
        return;

    m_thread_list.RefreshStateAfterStop();

    std::weak_ptr<ExceptionRecord> exception_record = m_session_data->m_debugger->GetActiveException();
    ExceptionRecordSP active_exception = exception_record.lock();
    if (!active_exception)
        return;

    StopInfoSP stop_info;
    ThreadSP stop_thread = m_thread_list.GetSelectedThread();
    RegisterContextSP register_context = stop_thread->GetRegisterContext();

    uint64_t pc = register_context->GetPC();
    if (active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT)
    {
        // TODO(zturner): The current EIP is AFTER the BP opcode, which is one byte.  So
        // to find the breakpoint, move the PC back.  A better way to do this is probably
        // to ask the Platform how big a breakpoint opcode is.
        --pc;
        BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
        lldb::break_id_t break_id = LLDB_INVALID_BREAK_ID;
        bool should_stop = true;
        if (site)
        {
            should_stop = site->ValidForThisThread(stop_thread.get());
            break_id = site->GetID();
        }

        stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*stop_thread, break_id, should_stop);
        stop_thread->SetStopInfo(stop_info);
    }
    else
    {
        std::string desc;
        llvm::raw_string_ostream desc_stream(desc);
        desc_stream << "Exception " << active_exception->GetExceptionCode() << " encountered at address " << pc;
        stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str());
        stop_thread->SetStopInfo(stop_info);
    }
}

bool
ProcessWindows::IsAlive()
{
    StateType state = GetPrivateState();
    switch (state)
    {
        case eStateCrashed:
        case eStateDetached:
        case eStateUnloaded:
        case eStateExited:
        case eStateInvalid:
            return false;
        default:
            return true;
    }
}

Error
ProcessWindows::DoHalt(bool &caused_stop)
{
    Error error;
    StateType state = GetPrivateState();
    if (state == eStateStopped)
        caused_stop = false;
    else
    {
        llvm::sys::ScopedLock lock(m_mutex);
        caused_stop = ::DebugBreakProcess(m_session_data->m_debugger->GetProcess().GetNativeProcess().GetSystemHandle());
        if (!caused_stop)
            error.SetError(GetLastError(), eErrorTypeWin32);
    }
    return error;
}

void ProcessWindows::DidLaunch()
{
    llvm::sys::ScopedLock lock(m_mutex);

    StateType state = GetPrivateState();
    // The initial stop won't broadcast the state change event, so account for that here.
    if (m_session_data && GetPrivateState() == eStateStopped &&
            m_session_data->m_launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
        RefreshStateAfterStop();
}

size_t
ProcessWindows::DoReadMemory(lldb::addr_t vm_addr,
                             void *buf,
                             size_t size,
                             Error &error)
{
    llvm::sys::ScopedLock lock(m_mutex);

    if (!m_session_data)
        return 0;

    HostProcess process = m_session_data->m_debugger->GetProcess();
    void *addr = reinterpret_cast<void *>(vm_addr);
    SIZE_T bytes_read = 0;
    if (!ReadProcessMemory(process.GetNativeProcess().GetSystemHandle(), addr, buf, size, &bytes_read))
        error.SetError(GetLastError(), eErrorTypeWin32);
    return bytes_read;
}

size_t
ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size, Error &error)
{
    llvm::sys::ScopedLock lock(m_mutex);

    if (!m_session_data)
        return 0;

    HostProcess process = m_session_data->m_debugger->GetProcess();
    void *addr = reinterpret_cast<void *>(vm_addr);
    SIZE_T bytes_written = 0;
    lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
    if (WriteProcessMemory(handle, addr, buf, size, &bytes_written))
        FlushInstructionCache(handle, addr, bytes_written);
    else
        error.SetError(GetLastError(), eErrorTypeWin32);
    return bytes_written;
}

lldb::addr_t
ProcessWindows::GetImageInfoAddress()
{
    Target &target = GetTarget();
    ObjectFile *obj_file = target.GetExecutableModule()->GetObjectFile();
    Address addr = obj_file->GetImageInfoAddress(&target);
    if (addr.IsValid())
        return addr.GetLoadAddress(&target);
    else
        return LLDB_INVALID_ADDRESS;
}

bool
ProcessWindows::CanDebug(Target &target, bool plugin_specified_by_name)
{
    if (plugin_specified_by_name)
        return true;

    // For now we are just making sure the file exists for a given module
    ModuleSP exe_module_sp(target.GetExecutableModule());
    if (exe_module_sp.get())
        return exe_module_sp->GetFileSpec().Exists();
    return false;
}

void
ProcessWindows::OnExitProcess(uint32_t exit_code)
{
    // No need to acquire the lock since m_session_data isn't accessed.

    ModuleSP executable_module = GetTarget().GetExecutableModule();
    ModuleList unloaded_modules;
    unloaded_modules.Append(executable_module);
    GetTarget().ModulesDidUnload(unloaded_modules, true);

    SetProcessExitStatus(nullptr, GetID(), true, 0, exit_code);
    SetPrivateState(eStateExited);
}

void
ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base)
{
    // Either we successfully attached to an existing process, or we successfully launched a new
    // process under the debugger.
    ModuleSP module = GetTarget().GetExecutableModule();
    bool load_addr_changed;
    module->SetLoadAddress(GetTarget(), image_base, false, load_addr_changed);

    // Notify the target that the executable module has loaded.  This will cause any pending
    // breakpoints to be resolved to explicit brekapoint sites.
    ModuleList loaded_modules;
    loaded_modules.Append(module);
    GetTarget().ModulesDidLoad(loaded_modules);

    llvm::sys::ScopedLock lock(m_mutex);

    DebuggerThreadSP debugger = m_session_data->m_debugger;
    const HostThreadWindows &wmain_thread = debugger->GetMainThread().GetNativeThread();
    m_session_data->m_new_threads[wmain_thread.GetThreadId()] = debugger->GetMainThread();
}

ExceptionResult
ProcessWindows::OnDebugException(bool first_chance, const ExceptionRecord &record)
{
    llvm::sys::ScopedLock lock(m_mutex);

    // FIXME: Without this check, occasionally when running the test suite there is
    // an issue where m_session_data can be null.  It's not clear how this could happen
    // but it only surfaces while running the test suite.  In order to properly diagnose
    // this, we probably need to first figure allow the test suite to print out full
    // lldb logs, and then add logging to the process plugin.
    if (!m_session_data)
        return ExceptionResult::SendToApplication;

    ExceptionResult result = ExceptionResult::SendToApplication;
    switch (record.GetExceptionCode())
    {
        case EXCEPTION_BREAKPOINT:
            // Handle breakpoints at the first chance.
            result = ExceptionResult::BreakInDebugger;

            if (!m_session_data->m_initial_stop_received)
            {
                m_session_data->m_initial_stop_received = true;
                ::SetEvent(m_session_data->m_initial_stop_event);
            }

            break;
        default:
            // For non-breakpoints, give the application a chance to handle the exception first.
            if (first_chance)
                result = ExceptionResult::SendToApplication;
            else
                result = ExceptionResult::BreakInDebugger;
    }

    if (!first_chance)
    {
        // Any second chance exception is an application crash by definition.
        SetPrivateState(eStateCrashed);
    }
    else if (result == ExceptionResult::BreakInDebugger)
    {
        // For first chance exceptions that we can handle, the process is stopped so the user
        // can interact with the debugger.
        SetPrivateState(eStateStopped);
    }
    else
    {
        // For first chance exceptions that we either eat or send back to the application, don't
        // modify the state of the application.
    }

    return result;
}

void
ProcessWindows::OnCreateThread(const HostThread &new_thread)
{
    llvm::sys::ScopedLock lock(m_mutex);

    const HostThreadWindows &wnew_thread = new_thread.GetNativeThread();
    m_session_data->m_new_threads[wnew_thread.GetThreadId()] = new_thread;
}

void
ProcessWindows::OnExitThread(const HostThread &exited_thread)
{
    llvm::sys::ScopedLock lock(m_mutex);

    // A thread may have started and exited before the debugger stopped allowing a refresh.
    // Just remove it from the new threads list in that case.
    const HostThreadWindows &wexited_thread = exited_thread.GetNativeThread();
    auto iter = m_session_data->m_new_threads.find(wexited_thread.GetThreadId());
    if (iter != m_session_data->m_new_threads.end())
        m_session_data->m_new_threads.erase(iter);
    else
        m_session_data->m_exited_threads[wexited_thread.GetThreadId()] = exited_thread;
}

void
ProcessWindows::OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr)
{
    // Confusingly, there is no Target::AddSharedModule.  Instead, calling GetSharedModule() with
    // a new module will add it to the module list and return a corresponding ModuleSP.
    Error error;
    ModuleSP module = GetTarget().GetSharedModule(module_spec, &error);
    bool load_addr_changed = false;
    module->SetLoadAddress(GetTarget(), module_addr, false, load_addr_changed);

    ModuleList loaded_modules;
    loaded_modules.Append(module);
    GetTarget().ModulesDidLoad(loaded_modules);
}

void
ProcessWindows::OnUnloadDll(lldb::addr_t module_addr)
{
    Address resolved_addr;
    if (GetTarget().ResolveLoadAddress(module_addr, resolved_addr))
    {
        ModuleSP module = resolved_addr.GetModule();
        if (module)
        {
            ModuleList unloaded_modules;
            unloaded_modules.Append(module);
            GetTarget().ModulesDidUnload(unloaded_modules, false);
        }
    }
}

void
ProcessWindows::OnDebugString(const std::string &string)
{
}

void
ProcessWindows::OnDebuggerError(const Error &error, uint32_t type)
{
    llvm::sys::ScopedLock lock(m_mutex);

    if (!m_session_data->m_initial_stop_received)
    {
        // If we haven't actually launched the process yet, this was an error launching the
        // process.  Set the internal error and signal the initial stop event so that the DoLaunch
        // method wakes up and returns a failure.
        m_session_data->m_launch_error = error;
        ::SetEvent(m_session_data->m_initial_stop_event);
        return;
    }

    // This happened while debugging.  Do we shutdown the debugging session, try to continue,
    // or do something else?
}
