// 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/breakpoint_impl.h"

#include <inttypes.h>

#include <algorithm>
#include <map>
#include <sstream>

#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/shared/zx_status.h"
#include "src/developer/debug/zxdb/client/breakpoint_location_impl.h"
#include "src/developer/debug/zxdb/client/breakpoint_observer.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/remote_api.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/system.h"
#include "src/developer/debug/zxdb/client/target.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/expr/permissive_input_location.h"
#include "src/developer/debug/zxdb/symbols/loaded_module_symbols.h"
#include "src/developer/debug/zxdb/symbols/module_symbols.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/developer/debug/zxdb/symbols/resolve_options.h"
#include "src/developer/debug/zxdb/symbols/target_symbols.h"

namespace zxdb {

namespace {

uint32_t next_breakpoint_id = 1;

debug_ipc::Stop SettingsStopToIpcStop(BreakpointSettings::StopMode mode) {
  switch (mode) {
    case BreakpointSettings::StopMode::kNone:
      return debug_ipc::Stop::kNone;
    case BreakpointSettings::StopMode::kThread:
      return debug_ipc::Stop::kThread;
    case BreakpointSettings::StopMode::kProcess:
      return debug_ipc::Stop::kProcess;
    case BreakpointSettings::StopMode::kAll:
      return debug_ipc::Stop::kAll;
  }
}

}  // namespace

struct BreakpointImpl::ProcessRecord {
  // Helper to return whether there are any enabled locations for this process.
  bool HasEnabledLocation() const {
    for (const auto& loc : locs) {
      if (loc.second.IsEnabled())
        return true;
    }
    return false;
  }

  // Helper to add a list of locations to the locs array. Returns true if anything was added (this
  // makes the call site cleaner).
  bool AddLocations(BreakpointImpl* bp, Process* process, const std::vector<Location>& locations) {
    for (const auto& loc : locations) {
      locs.emplace(std::piecewise_construct, std::forward_as_tuple(loc.address()),
                   std::forward_as_tuple(bp, process, loc.address()));
    }
    return !locations.empty();
  }

  // Set when we're registered as an observer for this process.
  bool observing = false;

  // All resolved locations indexed by address.
  std::map<uint64_t, BreakpointLocationImpl> locs;
};

BreakpointImpl::BreakpointImpl(Session* session, bool is_internal)
    : Breakpoint(session),
      is_internal_(is_internal),
      backend_id_(next_breakpoint_id++),
      impl_weak_factory_(this) {
  session->process_observers().AddObserver(this);
  session->target_observers().AddObserver(this);
}

BreakpointImpl::~BreakpointImpl() {
  if (backend_installed_ && settings_.enabled) {
    // Breakpoint was installed and the process still exists.
    settings_.enabled = false;
    SendBackendRemove();
  }

  session()->target_observers().RemoveObserver(this);
  session()->process_observers().RemoveObserver(this);
  if (registered_as_thread_observer_)
    session()->thread_observers().RemoveObserver(this);
}

BreakpointSettings BreakpointImpl::GetSettings() const { return settings_; }

void BreakpointImpl::SetSettings(const BreakpointSettings& settings) {
  settings_ = settings;

  bool changed = false;
  for (Target* target : session()->system().GetTargets()) {
    Process* process = target->GetProcess();
    if (process && CouldApplyToProcess(process))
      changed |= RegisterProcess(process);
  }

  // Add or remove thread notifications as required.
  if (settings_.scope.thread() && !registered_as_thread_observer_) {
    session()->thread_observers().AddObserver(this);
    registered_as_thread_observer_ = true;
  } else if (!settings_.scope.thread() && registered_as_thread_observer_) {
    session()->thread_observers().RemoveObserver(this);
    registered_as_thread_observer_ = false;
  }

  SyncBackend();

  if (changed && !IsInternal()) {
    for (auto& observer : session()->breakpoint_observers())
      observer.OnBreakpointMatched(this, true);
  }
}

bool BreakpointImpl::IsInternal() const { return is_internal_; }

std::vector<const BreakpointLocation*> BreakpointImpl::GetLocations() const {
  std::vector<const BreakpointLocation*> result;
  for (auto& proc : procs_) {
    for (auto& pair : proc.second.locs)
      result.push_back(&pair.second);
  }
  return result;
}

std::vector<BreakpointLocation*> BreakpointImpl::GetLocations() {
  std::vector<BreakpointLocation*> result;
  for (auto& proc : procs_) {
    for (auto& pair : proc.second.locs)
      result.push_back(&pair.second);
  }
  return result;
}

debug_ipc::BreakpointStats BreakpointImpl::GetStats() { return stats_; }

void BreakpointImpl::UpdateStats(const debug_ipc::BreakpointStats& stats) { stats_ = stats; }

void BreakpointImpl::BackendBreakpointRemoved() { backend_installed_ = false; }

void BreakpointImpl::WillDestroyTarget(Target* target) {
  if (target == settings_.scope.target()) {
    // As with threads going away, when the target goes away for a target-scoped breakpoint, convert
    // to a disabled system-wide breakpoint.
    settings_.scope = ExecutionScope();
    settings_.enabled = false;
  }
}

void BreakpointImpl::DidCreateProcess(Process* process, bool autoattached) {
  if (CouldApplyToProcess(process)) {
    if (RegisterProcess(process)) {
      SyncBackend();

      if (!IsInternal()) {
        for (auto& observer : session()->breakpoint_observers())
          observer.OnBreakpointMatched(this, false);
      }
    }
  }
}

void BreakpointImpl::WillDestroyProcess(Process* process, ProcessObserver::DestroyReason,
                                        int exit_code) {
  auto found = procs_.find(process);
  if (found == procs_.end())
    return;

  // Only need to update the backend if there was an enabled address associated with this process.
  bool send_update = found->second.HasEnabledLocation();

  // When the process exits, disable breakpoints that are entirely address-based since the addresses
  // will normally change when a process is loaded.
  if (AllLocationsAddresses())
    settings_.enabled = false;

  procs_.erase(found);

  // Needs to be done after the ProcessRecord is removed.
  if (send_update)
    SyncBackend();
}

void BreakpointImpl::DidLoadModuleSymbols(Process* process, LoadedModuleSymbols* module) {
  if (!CouldApplyToProcess(process))
    return;  // Irrelevant process.

  FindNameContext find_context(process->GetSymbols());

  ResolveOptions options = GetResolveOptions();
  bool needs_sync = false;
  for (const auto& loc : ExpandPermissiveInputLocationNames(find_context, settings_.locations)) {
    needs_sync |=
        procs_[process].AddLocations(this, process, module->ResolveInputLocation(loc, options));
  }

  if (needs_sync) {
    SyncBackend();

    if (!IsInternal()) {
      for (auto& observer : session()->breakpoint_observers())
        observer.OnBreakpointMatched(this, false);
    }
  }
}

void BreakpointImpl::WillUnloadModuleSymbols(Process* process, LoadedModuleSymbols* module) {
  // TODO(bug 61248) need to get the address range of this module and then remove all breakpoints in
  // that range.
}

void BreakpointImpl::WillDestroyThread(Thread* thread) {
  if (settings_.scope.thread() == thread) {
    // When the thread is destroyed that the breakpoint is associated with, disable the breakpoint
    // and convert to a target-scoped breakpoint. This will preserve its state without us having to
    // maintain some "defunct thread" association. The user can associate it with a new thread and
    // re-enable as desired.
    settings_.scope = ExecutionScope(thread->GetProcess()->GetTarget());
    settings_.enabled = false;

    // Don't need more thread notifications.
    FX_DCHECK(registered_as_thread_observer_);
    session()->thread_observers().RemoveObserver(this);
    registered_as_thread_observer_ = false;
  }
}

void BreakpointImpl::SyncBackend() {
  bool has_locations = HasEnabledLocation();

  if (backend_installed_ && !has_locations) {
    SendBackendRemove();
  } else if (has_locations) {
    SendBackendAddOrChange();
  }
  // Otherwise the backend doesn't know about it and we don't require anything.
}

void BreakpointImpl::SendBackendAddOrChange() {
  backend_installed_ = true;

  debug_ipc::AddOrChangeBreakpointRequest request;
  request.breakpoint.id = backend_id_;
  request.breakpoint.type = settings_.type;
  request.breakpoint.name = settings_.name;
  request.breakpoint.stop = SettingsStopToIpcStop(settings_.stop_mode);
  request.breakpoint.one_shot = settings_.one_shot;

  for (const auto& proc : procs_) {
    for (const auto& pair : proc.second.locs) {
      if (!pair.second.IsEnabled())
        continue;

      debug_ipc::ProcessBreakpointSettings addition;
      addition.process_koid = proc.first->GetKoid();

      if (settings_.scope.type() == ExecutionScope::kThread) {
        if (Thread* thread = settings_.scope.thread())
          addition.thread_koid = thread->GetKoid();
      }

      if (BreakpointSettings::TypeHasSize(settings_.type)) {
        uint64_t address = pair.second.address();
        addition.address_range = {address, address + settings_.byte_size};
      } else {
        addition.address = pair.second.address();
      }
      request.breakpoint.locations.push_back(addition);
    }
  }

  session()->remote_api()->AddOrChangeBreakpoint(
      request, [breakpoint = impl_weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::AddOrChangeBreakpointReply reply) {
        if (breakpoint)
          breakpoint->OnAddOrChangeComplete(err, std::move(reply));
      });
}

void BreakpointImpl::SendBackendRemove() {
  debug_ipc::RemoveBreakpointRequest request;
  request.breakpoint_id = backend_id_;

  session()->remote_api()->RemoveBreakpoint(
      request, [breakpoint = impl_weak_factory_.GetWeakPtr()](
                   const Err& err, debug_ipc::RemoveBreakpointReply reply) {
        if (breakpoint)
          breakpoint->OnRemoveComplete(err, std::move(reply));
      });

  backend_installed_ = false;
}

void BreakpointImpl::OnAddOrChangeComplete(const Err& input_err,
                                           debug_ipc::AddOrChangeBreakpointReply reply) {
  Err err = input_err;  // Could be a transport error.
  if (err.ok() && reply.status != 0) {
    // Transport succeeded but the backend failed.
    std::stringstream ss;
    ss << "System reported error " << reply.status << " ("
       << debug_ipc::ZxStatusToString(reply.status) << ")";
    if (reply.status == debug_ipc::kZxErrNoResources) {
      ss << std::endl
         << "Is this a hardware breakpoint? Check \"sys-info\" to "
            "verify the amount available within the system.";
    } else if (reply.status == debug_ipc::kZxErrNotSupported) {
      ss << std::endl
         << "This kernel command-line flag \"kernel.enable-debugging-syscalls\" is\n"
            "likely not set.";
    }
    err = Err(ss.str());
  }

  if (err.has_error()) {
    for (auto& observer : session()->breakpoint_observers())
      observer.OnBreakpointUpdateFailure(this, err);
  }
}

void BreakpointImpl::OnRemoveComplete(const Err& err, debug_ipc::RemoveBreakpointReply reply) {
  if (err.has_error()) {
    for (auto& observer : session()->breakpoint_observers())
      observer.OnBreakpointUpdateFailure(this, err);
  }
}

void BreakpointImpl::DidChangeLocation() { SyncBackend(); }

bool BreakpointImpl::CouldApplyToProcess(Process* process) const {
  // When applied to all processes, we need all notifications.
  if (settings_.scope.type() == ExecutionScope::kSystem)
    return true;

  // Target- and thread-specific breakpoints only watch their process.
  return settings_.scope.target() == process->GetTarget();
}

bool BreakpointImpl::HasEnabledLocation() const {
  if (!settings_.enabled)
    return false;
  for (const auto& proc : procs_) {
    if (proc.second.HasEnabledLocation())
      return true;
  }
  return false;
}

bool BreakpointImpl::RegisterProcess(Process* process) {
  // Clear existing locations for this process.
  ProcessRecord& record = procs_[process];
  bool changed = !record.locs.empty();
  record.locs.clear();

  // Resolve addresses.
  ResolveOptions options = GetResolveOptions();
  FindNameContext find_context(process->GetSymbols());

  changed |=
      record.AddLocations(this, process,
                          ResolvePermissiveInputLocations(process->GetSymbols(), options,
                                                          find_context, settings_.locations));
  return changed;
}

ResolveOptions BreakpointImpl::GetResolveOptions() const {
  ResolveOptions options;
  // We don't need the result to be symbolized unless required by skip_function_prologue.

  if (AllLocationsAddresses()) {
    // Only need addresses. Don't try to skip function prologues when the user gives an address or
    // the address might move.
    options.symbolize = false;
    options.skip_function_prologue = false;
  } else {
    // When breaking on symbols or lines, skip function prologues so the function parameters
    // can be displayed properly (they're not always correct in the prologue) as well as backtraces
    // (on ARM, the link register is saved in the prologue so things may look funny before that).
    // Function prologues require symbolization so we ask for both.
    //
    // TODO(bug 45309) we will need an option to control this like other debuggers. LLDB has a
    // per-breakpoint setting and a global default preference. In GDB you can do "break *Foo" to
    // skip the prologue.
    options.symbolize = true;
    options.skip_function_prologue = true;
  }

  return options;
}

bool BreakpointImpl::AllLocationsAddresses() const {
  return !settings_.locations.empty() &&
         std::all_of(settings_.locations.begin(), settings_.locations.end(),
                     [](const auto& loc) { return loc.type == InputLocation::Type::kAddress; });
}

}  // namespace zxdb
