// Copyright 2019 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/stack.h"

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

#include <map>

#include "src/developer/debug/ipc/records.h"
#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/client/arch_info.h"
#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/frame_fingerprint.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/expr/abi.h"
#include "src/developer/debug/zxdb/expr/eval_context_impl.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/lib/fxl/macros.h"

namespace zxdb {

namespace {

// Implementation of Frame for inlined frames. Inlined frames have a different location in the
// source code, but refer to the underlying physical frame for most data.
class InlineFrame final : public Frame {
 public:
  // The physical_frame must outlive this class. Normally both are owned by the Stack and have the
  // same lifetime.
  InlineFrame(Frame* physical_frame, Location loc)
      : Frame(physical_frame->session()), physical_frame_(physical_frame), location_(loc) {}
  ~InlineFrame() override = default;

  // Frame implementation.
  Thread* GetThread() const override { return physical_frame_->GetThread(); }
  bool IsInline() const override { return true; }
  const Frame* GetPhysicalFrame() const override { return physical_frame_; }
  const Location& GetLocation() const override { return location_; }
  uint64_t GetAddress() const override { return location_.address(); }
  debug_ipc::StackFrame::Trust GetTrust() const override { return physical_frame_->GetTrust(); }
  const std::vector<debug::RegisterValue>* GetRegisterCategorySync(
      debug::RegisterCategory category) const override {
    return physical_frame_->GetRegisterCategorySync(category);
  }
  void GetRegisterCategoryAsync(
      debug::RegisterCategory category, bool always_request,
      fit::function<void(const Err&, const std::vector<debug::RegisterValue>&)> cb) override {
    return physical_frame_->GetRegisterCategoryAsync(category, always_request, std::move(cb));
  }
  void WriteRegister(debug::RegisterID id, std::vector<uint8_t> data,
                     fit::callback<void(const Err&)> cb) override {
    return physical_frame_->WriteRegister(id, std::move(data), std::move(cb));
  }
  std::optional<uint64_t> GetBasePointer() const override {
    return physical_frame_->GetBasePointer();
  }
  void GetBasePointerAsync(fit::callback<void(uint64_t bp)> cb) override {
    return physical_frame_->GetBasePointerAsync(std::move(cb));
  }
  uint64_t GetCanonicalFrameAddress() const override {
    return physical_frame_->GetCanonicalFrameAddress();
  }
  uint64_t GetStackPointer() const override { return physical_frame_->GetStackPointer(); }
  fxl::RefPtr<SymbolDataProvider> GetSymbolDataProvider() const override {
    return physical_frame_->GetSymbolDataProvider();
  }
  fxl::RefPtr<EvalContext> GetEvalContext() const override {
    if (!symbol_eval_context_) {
      // Tolerate a null thread here because it makes testing much simpler. The EvalContext supports
      // a null ProcessSymbols for this case.
      fxl::WeakPtr<const ProcessSymbols> process_syms;
      if (Thread* thread = GetThread())
        process_syms = thread->GetProcess()->GetSymbols()->GetWeakPtr();
      symbol_eval_context_ = fxl::MakeRefCounted<EvalContextImpl>(
          session()->arch_info().abi(), process_syms, GetSymbolDataProvider(), location_);
    }
    return symbol_eval_context_;
  }
  bool IsAmbiguousInlineLocation() const override {
    const Location& loc = GetLocation();

    // Extract the inline function.
    if (!loc.symbol())
      return false;
    const Function* function = loc.symbol().Get()->As<Function>();
    if (!function)
      return false;
    if (!function->is_inline())
      return false;

    // There could be multiple code ranges for the inlined function, consider any of them as being a
    // candidate.
    for (const auto& cur : function->GetAbsoluteCodeRanges(loc.symbol_context())) {
      if (loc.address() == cur.begin())
        return true;
    }
    return false;
  }

 private:
  Frame* physical_frame_;  // Non-owning.
  Location location_;

  mutable fxl::RefPtr<EvalContextImpl> symbol_eval_context_;  // Lazy.

  FXL_DISALLOW_COPY_AND_ASSIGN(InlineFrame);
};

// Returns a fixed-up location referring to an indexed element in an inlined function call chain.
// This also handles the case where there are no inline calls and the function is the only one (this
// returns the same location).
//
// The main_location is the location returned by symbol lookup for the current address.
Location LocationForInlineFrameChain(const std::vector<fxl::RefPtr<Function>>& inline_chain,
                                     size_t chain_index, const Location& main_location) {
  // The file/line is the call location of the next (into the future) inlined function. Fall back on
  // the file/line from the main lookup.
  const FileLine* new_line = &main_location.file_line();
  int new_column = main_location.column();
  if (chain_index > 0) {
    const Function* next_call = inline_chain[chain_index - 1].get();
    if (next_call->call_line().is_valid()) {
      new_line = &next_call->call_line();
      new_column = 0;  // DWARF doesn't contain inline call column.
    }
  }

  return Location(main_location.address(), *new_line, new_column, main_location.symbol_context(),
                  inline_chain[chain_index]);
}

}  // namespace

Stack::Stack(Delegate* delegate) : delegate_(delegate), weak_factory_(this) {}

Stack::~Stack() = default;

fxl::WeakPtr<Stack> Stack::GetWeakPtr() { return weak_factory_.GetWeakPtr(); }

std::optional<size_t> Stack::IndexForFrame(const Frame* frame) const {
  for (size_t i = hide_ambiguous_inline_frame_count_; i < frames_.size(); i++) {
    if (frames_[i].get() == frame)
      return i - hide_ambiguous_inline_frame_count_;
  }
  return std::nullopt;
}

size_t Stack::InlineDepthForIndex(size_t index) const {
  FX_DCHECK(index < frames_.size());
  for (size_t depth = 0; index + depth < frames_.size(); depth++) {
    if (!frames_[index + depth]->IsInline())
      return depth;
  }

  FX_NOTREACHED();  // Should have found a physical frame that generated it.
  return 0;
}

FrameFingerprint Stack::GetFrameFingerprint(size_t virtual_frame_index) const {
  size_t frame_index = virtual_frame_index + hide_ambiguous_inline_frame_count_;

  // Should reference a valid index in the array.
  if (frame_index >= frames_.size()) {
    FX_NOTREACHED();
    return FrameFingerprint();
  }

  // The inline frame count is the number of steps from the requested frame index to the current
  // physical frame.
  size_t inline_count = InlineDepthForIndex(frame_index);

  return FrameFingerprint(frames_[frame_index]->GetCanonicalFrameAddress(), inline_count);
}

size_t Stack::GetAmbiguousInlineFrameCount() const {
  // This can't be InlineDepthForIndex() because that takes an index relative to the
  // hide_ambiguous_inline_frame_count_ and this function always wants to return the same thing
  // regardless of the hide count.
  for (size_t i = 0; i < frames_.size(); i++) {
    if (!frames_[i]->IsAmbiguousInlineLocation())
      return i;
  }

  // Should always have a non-inline frame if there are any.
  FX_DCHECK(frames_.empty());
  return 0;
}

void Stack::SetHideAmbiguousInlineFrameCount(size_t hide_count) {
  FX_DCHECK(hide_count <= GetAmbiguousInlineFrameCount());
  hide_ambiguous_inline_frame_count_ = hide_count;
}

void Stack::SyncFrames(const SyncFrameOptions& options, fit::callback<void(const Err&)> callback) {
  if (options.force_update)
    force_update_in_progress_ = true;
  delegate_->SyncFramesForStack(options, std::move(callback));
}

void Stack::SetFrames(debug_ipc::ThreadRecord::StackAmount amount,
                      const std::vector<debug_ipc::StackFrame>& new_frames) {
  bool initial_has_frames = !frames_.empty();

  // See if the new frames are an extension of the existing frames or are a replacement. This
  // avoids overwriting existing frames when possible because:
  //  - There may be in-process operations with weak references to the frame that we don't want
  //    to invalidate.
  //  - Inline frame state, especially with the hide_ambiguous_inline_frame_count_, needs to
  //    stay the same. Keeping this state across frame replacements and potential symbol changes
  //    isn't possible.
  size_t old_ambiguous_frame_count = GetAmbiguousInlineFrameCount();
  size_t old_hide_ambiguous_inline_frame_count = hide_ambiguous_inline_frame_count_;
  if (force_update_in_progress_) {
    // Replace all frames.
    hide_ambiguous_inline_frame_count_ = 0;
    frames_.clear();
  }

  size_t appending_from = 0;  // First index in new_frames to append.
  for (size_t i = 0; i < frames_.size(); i++) {
    // The input will not contain any inline frames so skip over those when doing the checking.
    if (frames_[i]->IsInline())
      continue;

    if (appending_from >= new_frames.size() ||
        frames_[i]->GetAddress() != new_frames[appending_from].ip ||
        frames_[i]->GetStackPointer() != new_frames[appending_from].sp) {
      // New frames are not a superset of our existing stack, replace everything.
      hide_ambiguous_inline_frame_count_ = 0;
      frames_.clear();
      appending_from = 0;
      break;
    }

    appending_from++;
  }

  for (size_t i = appending_from; i < new_frames.size(); i++)
    AppendFrame(new_frames[i]);

  has_all_frames_ = amount == debug_ipc::ThreadRecord::StackAmount::kFull;

  if (force_update_in_progress_ && old_ambiguous_frame_count == GetAmbiguousInlineFrameCount()) {
    // When forcing a refresh of the stack frames, optimistically assume that the actual stack
    // hasn't changed and the user wants the existing one re-evaluated (maybe with new symbols).
    // When the number of inline frames at the top of the stack hasn't changed, assume the old hide
    // count is also still valid and keep it from before.
    hide_ambiguous_inline_frame_count_ = old_hide_ambiguous_inline_frame_count;
  }

  force_update_in_progress_ = false;

  // Skip sending notifications when 0 frames replaced 0 frames.
  if (new_frames.size() != 0 || initial_has_frames)
    delegate_->DidUpdateStackFrames();
}

void Stack::SetFramesForTest(std::vector<std::unique_ptr<Frame>> frames, bool has_all) {
  frames_ = std::move(frames);
  has_all_frames_ = has_all;
  hide_ambiguous_inline_frame_count_ = 0;
  delegate_->DidUpdateStackFrames();
}

void Stack::ClearFrames() {
  has_all_frames_ = false;
  hide_ambiguous_inline_frame_count_ = 0;

  if (frames_.empty())
    return;  // Nothing to do.

  frames_.clear();
  delegate_->DidUpdateStackFrames();
}

Location Stack::SymbolizeFrameAddress(
    uint64_t address, debug_ipc::StackFrame::AddressType pc_is_return_address) const {
  // Adjust locations for non-topmost frames because we should display the locations of function
  // calls instead of return addresses. Inlined functions should also be expanded from the call
  // sites rather than the return sites.
  uint64_t address_to_symbolize = address;
  if (pc_is_return_address == debug_ipc::StackFrame::AddressType::kReturn)
    address_to_symbolize -= 1;

  // The symbols will provide the location for the innermost inlined function.
  Location loc = delegate_->GetSymbolizedLocationForAddress(address_to_symbolize);

  // Restore the actual address so that the register value and commands like "disassemble" are
  // still correct.
  if (pc_is_return_address == debug_ipc::StackFrame::AddressType::kReturn)
    loc.AddAddressOffset(1);

  return loc;
}

void Stack::AppendFrame(const debug_ipc::StackFrame& record) {
  // This symbolizes all stack frames since the expansion of inline frames depends on the symbols.
  // Its possible some stack objects will never have their frames queried which makes this duplicate
  // work. A possible addition is to just save the debug_ipc::StackFrames and only expand the inline
  // frames when the frame list is accessed.

  Location inner_loc = SymbolizeFrameAddress(record.ip, record.pc_is_return_address);

  const Function* cur_func = inner_loc.symbol().Get()->As<Function>();
  if (!cur_func) {
    // No function associated with this location.
    frames_.push_back(delegate_->MakeFrameForStack(record, inner_loc));
    return;
  }

  // The Location object will reference the most-specific inline function but
  // we need the whole chain.
  std::vector<fxl::RefPtr<Function>> inline_chain = cur_func->GetInlineChain();
  if (inline_chain.back()->is_inline()) {
    // A non-inline frame was not found. The symbols are corrupt so give up on inline processing and
    // add the physical frame only.
    frames_.push_back(delegate_->MakeFrameForStack(record, inner_loc));
    return;
  }

  // Need to make the base "physical" frame first because all of the inline frames refer to it.
  auto physical_frame = delegate_->MakeFrameForStack(
      record, LocationForInlineFrameChain(inline_chain, inline_chain.size() - 1, inner_loc));

  // Add inline functions (skipping the last which is the physical frame made above).
  for (size_t i = 0; i < inline_chain.size() - 1; i++) {
    frames_.push_back(std::make_unique<InlineFrame>(
        physical_frame.get(), LocationForInlineFrameChain(inline_chain, i, inner_loc)));
  }

  // Physical frame goes last (back in time).
  frames_.push_back(std::move(physical_frame));
}

}  // namespace zxdb
