// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/client/finish_physical_frame_thread_controller.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/client/until_thread_controller.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/symbols/function.h"

namespace zxdb {

FinishPhysicalFrameThreadController::FinishPhysicalFrameThreadController(Stack& stack,
                                                                         size_t frame_to_finish,
                                                                         FunctionReturnCallback cb)
    : frame_to_finish_(frame_to_finish),
      function_return_callback_(std::move(cb)),
      weak_factory_(this) {
  FX_DCHECK(frame_to_finish < stack.size());
  FX_DCHECK(!stack[frame_to_finish]->IsInline());

  // Save the symbol being finished for later notifications.
  function_being_finished_ = stack[frame_to_finish]->GetLocation().symbol();

#ifndef NDEBUG
  // Stash for validation later.
  frame_ip_ = stack[frame_to_finish]->GetAddress();
#endif
}

FinishPhysicalFrameThreadController::~FinishPhysicalFrameThreadController() = default;

FinishPhysicalFrameThreadController::StopOp FinishPhysicalFrameThreadController::OnThreadStop(
    debug_ipc::ExceptionType stop_type,
    const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) {
  if (until_controller_) {
    if (auto op = until_controller_->OnThreadStop(stop_type, hit_breakpoints); op != kStopDone)
      return op;

    // The until controller said to stop. The CPU is now at the address immediately following the
    // function call. The tricky part is that this could be the first instruction of a new inline
    // function following the call and the stack will now contain that inline expansion. Our caller
    // expects to be in the frame that called the function being stepped out of.
    //
    // Rolling ambiguous frames back to "one before" the frame fingerprint being finished might
    // sound right but isn't because that fingerprint won't exist any more (we just exited it).
    //
    // For a frame to be ambiguous the IP must be at the first instruction of a range of that
    // inline. By virtue of just returning from a function call, we know any inline functions that
    // start immediately after the call weren't in the stack of the original call.
    Stack& stack = thread()->GetStack();
    stack.SetHideAmbiguousInlineFrameCount(stack.GetAmbiguousInlineFrameCount());

    if (function_return_callback_) {
      function_return_callback_(
          FunctionReturnInfo{.thread = thread(), .symbol = function_being_finished_});
    }

    return kStopDone;
  }

  // When there's no "until" controller, this controller just said "continue" to step out of the
  // oldest stack frame. Therefore, any stops at this level aren't ours.
  return kContinue;
}

void FinishPhysicalFrameThreadController::InitWithThread(Thread* thread,
                                                         fit::callback<void(const Err&)> cb) {
  SetThread(thread);

  Stack& stack = thread->GetStack();

#ifndef NDEBUG
  // The stack must not have changed from construction to this call. There are no async requests
  // that need to happen during this time, just registration with the thread. Otherwise the frame
  // fingerprint computation needs to be scheduled in the constructor which complicates the async
  // states of this function (though it's possible in the future if necessary).
  FX_DCHECK(stack.size() > frame_to_finish_);
  FX_DCHECK(stack[frame_to_finish_]->GetAddress() == frame_ip_);
#endif

  if (enable_debug_logging()) {
    auto function = stack[frame_to_finish_]->GetLocation().symbol().Get()->As<Function>();
    if (function)
      Log("Finishing %s", function->GetFullName().c_str());
    else
      Log("Finshing unsymbolized function");
  }

  InitWithFingerprint(stack.GetFrameFingerprint(frame_to_finish_));
  cb(Err());
}

ThreadController::ContinueOp FinishPhysicalFrameThreadController::GetContinueOp() {
  // Once this thread starts running, the frame index is invalid.
  frame_to_finish_ = static_cast<size_t>(-1);

  if (until_controller_)
    return until_controller_->GetContinueOp();

  // This will happen when there's no previous frame so there's no address to return to.
  // Unconditionally continue.
  return ContinueOp::Continue();
}

void FinishPhysicalFrameThreadController::InitWithFingerprint(FrameFingerprint fingerprint) {
  if (frame_to_finish_ >= thread()->GetStack().size() - 1) {
    // Finishing the last frame. There is no return address so there's no setup necessary to step,
    // just continue.
    return;
  }

  // The address we're returning to is that of the previous frame,
  uint64_t to_addr = thread()->GetStack()[frame_to_finish_ + 1]->GetAddress();
  if (!to_addr)
    return;  // Previous stack frame is null, just continue.

  until_controller_ = std::make_unique<UntilThreadController>(
      std::vector<InputLocation>{InputLocation(to_addr)}, fingerprint,
      UntilThreadController::kRunUntilOlderFrame);

  // Give the "until" controller a dummy callback and execute the callback ASAP. The until
  // controller executes the callback once it knows that the breakpoint set has been complete
  // (round-trip to the target system).
  //
  // Since we provide an address there's no weirdness with symbols and we don't have to worry about
  // matching 0 locations. If the breakpoint set fails, the caller address is invalid and stepping
  // is impossible so it doesn't matter. We can run faster without waiting for the round-trip, and
  // the IPC will serialize so the breakpoint set happens before the thread resume.
  until_controller_->InitWithThread(thread(), [](const Err&) {});
}

}  // namespace zxdb
