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

#include "lldb/Target/ThreadPlanCallFunction.h"

// C Includes
// C++ Includes
// Other libraries and framework includes

// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// ThreadPlanCallFunction: Plan to call a single function
//----------------------------------------------------------------------
bool
ThreadPlanCallFunction::ConstructorSetup (Thread &thread,
                                          ABI *& abi,
                                          lldb::addr_t &start_load_addr,
                                          lldb::addr_t &function_load_addr)
{
    SetIsMasterPlan (true);
    SetOkayToDiscard (false);
    SetPrivate (true);

    ProcessSP process_sp (thread.GetProcess());
    if (!process_sp)
        return false;

    abi = process_sp->GetABI().get();

    if (!abi)
        return false;

    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));

    SetBreakpoints();

    m_function_sp = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize();
    // If we can't read memory at the point of the process where we are planning to put our function, we're
    // not going to get any further...
    Error error;
    process_sp->ReadUnsignedIntegerFromMemory(m_function_sp, 4, 0, error);
    if (!error.Success())
    {
        m_constructor_errors.Printf ("Trying to put the stack in unreadable memory at: 0x%" PRIx64 ".", m_function_sp);
        if (log)
            log->Printf ("ThreadPlanCallFunction(%p): %s.",
                         static_cast<void*>(this),
                         m_constructor_errors.GetData());
        return false;
    }

    Module *exe_module = GetTarget().GetExecutableModulePointer();

    if (exe_module == NULL)
    {
        m_constructor_errors.Printf ("Can't execute code without an executable module.");
        if (log)
            log->Printf ("ThreadPlanCallFunction(%p): %s.",
                         static_cast<void*>(this),
                         m_constructor_errors.GetData());
        return false;
    }
    else
    {
        ObjectFile *objectFile = exe_module->GetObjectFile();
        if (!objectFile)
        {
            m_constructor_errors.Printf ("Could not find object file for module \"%s\".", 
                                         exe_module->GetFileSpec().GetFilename().AsCString());

            if (log)
                log->Printf ("ThreadPlanCallFunction(%p): %s.",
                             static_cast<void*>(this),
                             m_constructor_errors.GetData());
            return false;
        }

        m_start_addr = objectFile->GetEntryPointAddress();
        if (!m_start_addr.IsValid())
        {
            m_constructor_errors.Printf ("Could not find entry point address for executable module \"%s\".", 
                                         exe_module->GetFileSpec().GetFilename().AsCString());
            if (log)
                log->Printf ("ThreadPlanCallFunction(%p): %s.",
                             static_cast<void*>(this),
                             m_constructor_errors.GetData());
            return false;
        }
    }

    start_load_addr = m_start_addr.GetLoadAddress (&GetTarget());

    // Checkpoint the thread state so we can restore it later.
    if (log && log->GetVerbose())
        ReportRegisterState ("About to checkpoint thread before function call.  Original register state was:");

    if (!thread.CheckpointThreadState (m_stored_thread_state))
    {
        m_constructor_errors.Printf ("Setting up ThreadPlanCallFunction, failed to checkpoint thread state.");
        if (log)
            log->Printf ("ThreadPlanCallFunction(%p): %s.",
                         static_cast<void*>(this),
                         m_constructor_errors.GetData());
        return false;
    }
    function_load_addr = m_function_addr.GetLoadAddress (&GetTarget());

    return true;
}

ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
                                                const Address &function,
                                                const ClangASTType &return_type,
                                                llvm::ArrayRef<addr_t> args,
                                                const EvaluateExpressionOptions &options) :
    ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
    m_valid (false),
    m_stop_other_threads (options.GetStopOthers()),
    m_unwind_on_error (options.DoesUnwindOnError()),
    m_ignore_breakpoints (options.DoesIgnoreBreakpoints()),
    m_debug_execution (options.GetDebug()),
    m_trap_exceptions (options.GetTrapExceptions()),
    m_function_addr (function),
    m_function_sp (0),
    m_return_type (return_type),
    m_takedown_done (false),
    m_should_clear_objc_exception_bp(false),
    m_should_clear_cxx_exception_bp (false),
    m_stop_address (LLDB_INVALID_ADDRESS)
{
    lldb::addr_t start_load_addr;
    ABI *abi;
    lldb::addr_t function_load_addr;
    if (!ConstructorSetup (thread, abi, start_load_addr, function_load_addr))
        return;

    if (!abi->PrepareTrivialCall(thread,
                                 m_function_sp,
                                 function_load_addr,
                                 start_load_addr,
                                 args))
        return;

    ReportRegisterState ("Function call was set up.  Register state was:");

    m_valid = true;    
}

ThreadPlanCallFunction::~ThreadPlanCallFunction ()
{
    DoTakedown(PlanSucceeded());
}

void
ThreadPlanCallFunction::ReportRegisterState (const char *message)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP | LIBLLDB_LOG_VERBOSE));
    if (log)
    {
        StreamString strm;
        RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();

        log->PutCString(message);

        RegisterValue reg_value;

        for (uint32_t reg_idx = 0, num_registers = reg_ctx->GetRegisterCount();
             reg_idx < num_registers;
             ++reg_idx)
        {
            const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_idx);
            if (reg_ctx->ReadRegister(reg_info, reg_value))
            {
                reg_value.Dump(&strm, reg_info, true, false, eFormatDefault);
                strm.EOL();
            }
        }
        log->PutCString(strm.GetData());
    }
}

void
ThreadPlanCallFunction::DoTakedown (bool success)
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));

    if (!m_valid)
    {
        //Don't call DoTakedown if we were never valid to begin with.
        if (log)
            log->Printf ("ThreadPlanCallFunction(%p): Log called on ThreadPlanCallFunction that was never valid.",
                         static_cast<void*>(this));
        return;
    }

    if (!m_takedown_done)
    {
        if (success)
        {
            ProcessSP process_sp (m_thread.GetProcess());
            const ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
            if (abi && m_return_type.IsValid())
            {
                const bool persistent = false;
                m_return_valobj_sp = abi->GetReturnValueObject (m_thread, m_return_type, persistent);
            }
        }
        if (log)
            log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
                         static_cast<void*>(this), m_thread.GetID(), m_valid,
                         IsPlanComplete());
        m_takedown_done = true;
        m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
        m_real_stop_info_sp = GetPrivateStopInfo ();
        if (!m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state))
        {
            if (log)
                log->Printf("ThreadPlanCallFunction(%p): DoTakedown failed to restore register state",
                            static_cast<void*>(this));
        }
        SetPlanComplete(success);
        ClearBreakpoints();
        if (log && log->GetVerbose())
            ReportRegisterState ("Restoring thread state after function call.  Restored register state:");

    }
    else
    {
        if (log)
            log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called as no-op for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n",
                         static_cast<void*>(this), m_thread.GetID(), m_valid,
                         IsPlanComplete());
    }
}

void
ThreadPlanCallFunction::WillPop ()
{
    DoTakedown(PlanSucceeded());
}

void
ThreadPlanCallFunction::GetDescription (Stream *s, DescriptionLevel level)
{
    if (level == eDescriptionLevelBrief)
    {
        s->Printf("Function call thread plan");
    }
    else
    {
        TargetSP target_sp (m_thread.CalculateTarget());
        s->Printf("Thread plan to call 0x%" PRIx64, m_function_addr.GetLoadAddress(target_sp.get()));
    }
}

bool
ThreadPlanCallFunction::ValidatePlan (Stream *error)
{
    if (!m_valid)
    {
        if (error)
        {
            if (m_constructor_errors.GetSize() > 0)
                error->PutCString (m_constructor_errors.GetData());
            else
                error->PutCString ("Unknown error");
        }
        return false;
    }

    return true;
}


Vote
ThreadPlanCallFunction::ShouldReportStop(Event *event_ptr)
{
    if (m_takedown_done || IsPlanComplete())
        return eVoteYes;
    else
        return ThreadPlan::ShouldReportStop(event_ptr);
}

bool
ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
{    
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS));
    m_real_stop_info_sp = GetPrivateStopInfo ();
    
    // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
    // we answer yes.
    if (m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop(event_ptr))
    {
        SetPlanComplete();
        return true;
    }
    
    // Check if the breakpoint is one of ours.
    
    StopReason stop_reason;
    if (!m_real_stop_info_sp)
        stop_reason = eStopReasonNone;
    else
        stop_reason = m_real_stop_info_sp->GetStopReason();
    if (log)
        log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: Got stop reason - %s.", Thread::StopReasonAsCString(stop_reason));

    if (stop_reason == eStopReasonBreakpoint && BreakpointsExplainStop())
        return true;
    
    // One more quirk here.  If this event was from Halt interrupting the target, then we should not consider
    // ourselves complete.  Return true to acknowledge the stop.
    if (Process::ProcessEventData::GetInterruptedFromEvent(event_ptr))
    {
        if (log)
            log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: The event is an Interrupt, returning true.");
        return true;
    }
    // We control breakpoints separately from other "stop reasons."  So first,
    // check the case where we stopped for an internal breakpoint, in that case, continue on.
    // If it is not an internal breakpoint, consult m_ignore_breakpoints.
    
    
    if (stop_reason == eStopReasonBreakpoint)
    {
        ProcessSP process_sp (m_thread.CalculateProcess());
        uint64_t break_site_id = m_real_stop_info_sp->GetValue();
        BreakpointSiteSP bp_site_sp;
        if (process_sp)
            bp_site_sp = process_sp->GetBreakpointSiteList().FindByID(break_site_id);
        if (bp_site_sp)
        {
            uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
            bool is_internal = true;
            for (uint32_t i = 0; i < num_owners; i++)
            {
                Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
                if (log)
                    log->Printf ("ThreadPlanCallFunction::PlanExplainsStop: hit breakpoint %d while calling function", bp.GetID());
                
                if (!bp.IsInternal())
                {
                    is_internal = false;
                    break;
                }
            }
            if (is_internal)
            {
                if (log)
                    log->Printf ("ThreadPlanCallFunction::PlanExplainsStop hit an internal breakpoint, not stopping.");
                return false;
            }
        }

        if (m_ignore_breakpoints)
        {
            if (log)
                log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
            m_real_stop_info_sp->OverrideShouldStop(false);
            return true;
        }
        else
        {
            if (log)
                log->Printf("ThreadPlanCallFunction::PlanExplainsStop: we are not ignoring breakpoints, overriding breakpoint stop info ShouldStop, returning true");
            m_real_stop_info_sp->OverrideShouldStop(true);
            return false;
        }
    }
    else if (!m_unwind_on_error)
    {
        // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack.
        return false;
    }
    else
    {
        // If the subplan is running, any crashes are attributable to us.
        // If we want to discard the plan, then we say we explain the stop
        // but if we are going to be discarded, let whoever is above us
        // explain the stop.
        // But don't discard the plan if the stop would restart itself (for instance if it is a
        // signal that is set not to stop.  Check that here first.  We just say we explain the stop
        // but aren't done and everything will continue on from there.
        
        if (m_real_stop_info_sp && m_real_stop_info_sp->ShouldStopSynchronous(event_ptr))
        {
            SetPlanComplete(false);
            if (m_subplan_sp)
            {
                if (m_unwind_on_error)
                    return true;
                else
                    return false;
            }
            else
                return false;
        }
        else
            return true;
    }
}

bool
ThreadPlanCallFunction::ShouldStop (Event *event_ptr)
{
    // We do some computation in DoPlanExplainsStop that may or may not set the plan as complete.
    // We need to do that here to make sure our state is correct.
    DoPlanExplainsStop(event_ptr);
    
    if (IsPlanComplete())
    {
        ReportRegisterState ("Function completed.  Register state was:");
        return true;
    }
    else
    {
        return false;
    }
}

bool
ThreadPlanCallFunction::StopOthers ()
{
    return m_stop_other_threads;
}

StateType
ThreadPlanCallFunction::GetPlanRunState ()
{
    return eStateRunning;
}

void
ThreadPlanCallFunction::DidPush ()
{
//#define SINGLE_STEP_EXPRESSIONS
    
    // Now set the thread state to "no reason" so we don't run with whatever signal was outstanding...
    // Wait till the plan is pushed so we aren't changing the stop info till we're about to run.
    
    GetThread().SetStopInfoToNothing();
    
#ifndef SINGLE_STEP_EXPRESSIONS
    m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads));
    
    m_thread.QueueThreadPlan(m_subplan_sp, false);
    m_subplan_sp->SetPrivate (true);
#endif
}

bool
ThreadPlanCallFunction::WillStop ()
{
    return true;
}

bool
ThreadPlanCallFunction::MischiefManaged ()
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    if (IsPlanComplete())
    {
        if (log)
            log->Printf("ThreadPlanCallFunction(%p): Completed call function plan.",
                        static_cast<void*>(this));

        ThreadPlan::MischiefManaged ();
        return true;
    }
    else
    {
        return false;
    }
}

void
ThreadPlanCallFunction::SetBreakpoints ()
{
    ProcessSP process_sp (m_thread.CalculateProcess());
    if (m_trap_exceptions && process_sp)
    {
        m_cxx_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeC_plus_plus);
        m_objc_language_runtime = process_sp->GetLanguageRuntime(eLanguageTypeObjC);
    
        if (m_cxx_language_runtime)
        {
            m_should_clear_cxx_exception_bp = !m_cxx_language_runtime->ExceptionBreakpointsAreSet();
            m_cxx_language_runtime->SetExceptionBreakpoints();
        }
        if (m_objc_language_runtime)
        {
            m_should_clear_objc_exception_bp = !m_objc_language_runtime->ExceptionBreakpointsAreSet();
            m_objc_language_runtime->SetExceptionBreakpoints();
        }
    }
}

void
ThreadPlanCallFunction::ClearBreakpoints ()
{
    if (m_trap_exceptions)
    {
        if (m_cxx_language_runtime && m_should_clear_cxx_exception_bp)
            m_cxx_language_runtime->ClearExceptionBreakpoints();
        if (m_objc_language_runtime && m_should_clear_objc_exception_bp)
            m_objc_language_runtime->ClearExceptionBreakpoints();
    }
}

bool
ThreadPlanCallFunction::BreakpointsExplainStop()
{
    StopInfoSP stop_info_sp = GetPrivateStopInfo ();
    
    if (m_trap_exceptions)
    {
        if ((m_cxx_language_runtime &&
                m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
           ||(m_objc_language_runtime &&
                m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
        {
            Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
            if (log)
                log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
            
            SetPlanComplete(false);
            
            // If the user has set the ObjC language breakpoint, it would normally get priority over our internal
            // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
            stop_info_sp->OverrideShouldStop (true);
            return true;
        }
    }
    
    return false;
}

void
ThreadPlanCallFunction::SetStopOthers (bool new_value)
{
    m_subplan_sp->SetStopOthers(new_value);
}


bool
ThreadPlanCallFunction::RestoreThreadState()
{
    return GetThread().RestoreThreadStateFromCheckpoint(m_stored_thread_state);
}

