//===-- ThreadPlanCallFunction.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
// Project includes
#include "lldb/Target/ThreadPlanCallFunction.h"
#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 == nullptr) {
    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 CompilerType &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_takedown_done(false),
      m_should_clear_objc_exception_bp(false),
      m_should_clear_cxx_exception_bp(false),
      m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(return_type) {
  lldb::addr_t start_load_addr = LLDB_INVALID_ADDRESS;
  lldb::addr_t function_load_addr = LLDB_INVALID_ADDRESS;
  ABI *abi = nullptr;

  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(
    Thread &thread, const Address &function,
    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_takedown_done(false),
      m_should_clear_objc_exception_bp(false),
      m_should_clear_cxx_exception_bp(false),
      m_stop_address(LLDB_INVALID_ADDRESS), m_return_type(CompilerType()) {}

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) {
      SetReturnValue();
    }
    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 && 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);
      return m_subplan_sp ? m_unwind_on_error : 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);
}

void ThreadPlanCallFunction::SetReturnValue() {
  ProcessSP process_sp(m_thread.GetProcess());
  const ABI *abi = process_sp ? process_sp->GetABI().get() : nullptr;
  if (abi && m_return_type.IsValid()) {
    const bool persistent = false;
    m_return_valobj_sp =
        abi->GetReturnValueObject(m_thread, m_return_type, persistent);
  }
}
