// Copyright 2021 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/step_through_plt_thread_controller.h"

#include "src/developer/debug/zxdb/client/frame.h"
#include "src/developer/debug/zxdb/client/function_step.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/stack.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/developer/debug/zxdb/symbols/symbol.h"

namespace zxdb {

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

  const Stack& stack = thread->GetStack();
  if (stack.empty())
    return cb(Err("Can't step, no frames."));
  const Frame* top_frame = stack[0];

  // Extract the ELF PLT symbol for the current location (the thread should be stopped at a PLT
  // symbol when InitWithThread() is called).
  const Location& cur_loc = top_frame->GetLocation();
  if (!cur_loc.symbol()) {
    FX_NOTREACHED();
    return cb(Err("Expecting a PLT symbol to step through."));
  }
  const ElfSymbol* elf_sym = cur_loc.symbol().Get()->As<ElfSymbol>();
  if (!elf_sym || elf_sym->elf_type() != ElfSymbolType::kPlt) {
    FX_NOTREACHED();
    return cb(Err("Expecting a PLT symbol to step through."));
  }

  const std::string linkage_name = elf_sym->linkage_name();
  plt_address_ = cur_loc.address();

  // The PLT trampoline will have the same name as the destinaion symbols, they'll all be called,
  // for example, "open" and they'll all be a PLT type (so "$plt(open)" in zxdb naming).
  // Currently ELF symbol lookup only takes mangled names, so we need to construct an identifier
  // based on the linkage name.
  Identifier plt_name(IdentifierComponent(SpecialIdentifier::kPlt, linkage_name));
  FX_DCHECK(plt_name.components().size() == 1);  // Expect one component for all ELF symbols.

  // Get the elf symbol name because we don't want to just match PLT entries. Querying for
  // $elf(open) will also match $plt(open) because PLT symbols are a subset of ELF symbols. These
  // extra matches should be harmless: we'll filter out our current PLT symbols and other modules'
  // PLT entries for the same symbol just won't be hit.
  Identifier elf_name(IdentifierComponent(SpecialIdentifier::kElf, linkage_name));

  // We expect the function name to resolve to two locations: the current one (the calling PLT
  // entry) and the destination one. There might be additional ones if there are duplicate symbols
  // (yikes) or other modules importing the same function (normal) but if there is only one it's our
  // calling location and the destination is unresolved.
  //
  // We could pass the function name directly to the "Until" controller but it will also match
  // our current location and will hit when we try to continue.
  //
  // There is some extra logic in the breakpoint that the "until" controller makes about dynamically
  // loaded libraries (like if this PLT thunk actually causes a module to be loaded) that we may
  // want in the future. If that's the case, we may want to just pass the function name to the
  // "until" controller and reach into its breakpoint and disable the current location.
  auto found = thread->GetProcess()->GetSymbols()->ResolveInputLocation(InputLocation(elf_name));

  // Filter out the current IP.
  found.erase(
      std::remove_if(found.begin(), found.end(),
                     [ip = plt_address_](const Location& cur) { return cur.address() == ip; }),
      found.end());

  Log("Got %zu matches for ELF symbol %s, running 'until' there.", found.size(),
      plt_name.components()[0].name().c_str());

  // When no matches were found, the destination can never be hit. Using the "until" controller at
  // this point will be like continuing the program which will lose the current location. In this
  // case, give up and stop the program so the user can figure out what they want to do.
  if (found.empty()) {
    cb(Err("Could not find destination of PLT trampoline."));
    return;
  }

  // Make the "until" controller run until the resulting address(s). It's important that this
  // forward asynchronous failures back to our callback parameter because the breakpoint set could
  // fail (for example, the code could be in the read-only vDSO) and we don't want execution to just
  // continue in that case.
  std::vector<InputLocation> input_locations;
  for (const auto& loc : found) {
    dest_addrs_.push_back(loc.address());
    input_locations.push_back(InputLocation(loc.address()));
  }

  until_ = std::make_unique<UntilThreadController>(std::move(input_locations));
  until_->InitWithThread(
      thread, [weak_this = weak_factory_.GetWeakPtr(), cb = std::move(cb)](const Err& err) mutable {
        if (err.has_error() && weak_this)
          weak_this->OnUntilControllerInitializationFailed();
        cb(err);
      });
}

ThreadController::ContinueOp StepThroughPltThreadController::GetContinueOp() {
  if (until_)
    return until_->GetContinueOp();

  // Fall back to single-stepping instructions if the until controller failed.
  return ContinueOp::StepInstruction();
}

ThreadController::StopOp StepThroughPltThreadController::OnThreadStop(
    debug_ipc::ExceptionType stop_type,
    const std::vector<fxl::WeakPtr<Breakpoint>>& hit_breakpoints) {
  if (until_) {
    // Delegate to thread controller.
    Log("Checking with until controller to see if PLT stepping is complete.");
    return until_->OnThreadStop(stop_type, hit_breakpoints);
  }

  // We're single-stepping through the PLT, check against the addresses.
  if (!dest_addrs_.empty()) {
    Stack& stack = thread()->GetStack();
    if (stack.empty()) {
      Log("Unexpected empty stack");
      return kUnexpected;  // Agent sent bad state, give up trying to step.
    }
    const Frame* top_frame = stack[0];
    uint64_t ip = top_frame->GetAddress();

    for (auto addr : dest_addrs_) {
      if (addr == ip) {
        Log("Matched PLT destination for stepping.");
        return ThreadController::StopOp::kStopDone;
      }
    }

    Log("Continuing to single-step through PLT.");
    return ThreadController::StopOp::kContinue;
  }

  Log("No destination for PLT step, stopping execution.");
  return ThreadController::StopOp::kStopDone;
}

void StepThroughPltThreadController::OnUntilControllerInitializationFailed() {
  // The "until" controller failed to initialize. Most commonly this is because the breakpoint could
  // not be set because the destination memory is read-only (this will happen for syscalls which are
  // in the vDSO). Fall back to single-stepping through the trampoline.
  Log("Until controller failed, falling back to single-stepping through PLT.");
  until_ = nullptr;
}

}  // namespace zxdb
