// Copyright 2017 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include "object/excp_port.h"

#include <err.h>
#include <inttypes.h>
#include <string.h>
#include <trace.h>

#include <arch/exception.h>
#include <fbl/alloc_checker.h>
#include <object/job_dispatcher.h>
#include <object/port_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.h>

#define LOCAL_TRACE 0

static PortPacket* MakePacket(uint64_t key, uint32_t type, zx_koid_t pid, zx_koid_t tid) {
  if (!ZX_PKT_IS_EXCEPTION(type))
    return nullptr;

  auto port_packet = PortDispatcher::DefaultPortAllocator()->Alloc();
  if (!port_packet)
    return nullptr;

  port_packet->packet.key = key;
  port_packet->packet.type = type;
  port_packet->packet.status = ZX_OK;
  port_packet->packet.exception.pid = pid;
  port_packet->packet.exception.tid = tid;
  port_packet->packet.exception.reserved0 = 0;
  port_packet->packet.exception.reserved1 = 0;

  return port_packet;
}

// static
zx_status_t ExceptionPort::Create(Type type, fbl::RefPtr<PortDispatcher> port, uint64_t port_key,
                                  fbl::RefPtr<ExceptionPort>* out_eport) {
  fbl::AllocChecker ac;
  auto eport = new (&ac) ExceptionPort(type, ktl::move(port), port_key);
  if (!ac.check())
    return ZX_ERR_NO_MEMORY;

  // ExceptionPort's ctor causes the first ref to be adopted,
  // so we should only wrap.
  *out_eport = fbl::WrapRefPtr<ExceptionPort>(eport);
  return ZX_OK;
}

ExceptionPort::ExceptionPort(Type type, fbl::RefPtr<PortDispatcher> port, uint64_t port_key)
    : type_(type), port_key_(port_key), port_(port) {
  LTRACE_ENTRY_OBJ;
  DEBUG_ASSERT(port_ != nullptr);

  Guard<fbl::Mutex> guard{&lock_};
  port_->LinkExceptionPortEportLocked(this);
}

ExceptionPort::~ExceptionPort() {
  LTRACE_ENTRY_OBJ;
  DEBUG_ASSERT(port_ == nullptr);
  DEBUG_ASSERT(!InContainer());
  DEBUG_ASSERT(!IsBoundLocked());
}

void ExceptionPort::SetTarget(const fbl::RefPtr<JobDispatcher>& target) {
  canary_.Assert();

  LTRACE_ENTRY_OBJ;
  Guard<fbl::Mutex> guard{&lock_};
  DEBUG_ASSERT_MSG(type_ == Type::JOB || type_ == Type::JOB_DEBUGGER, "unexpected type %d",
                   static_cast<int>(type_));
  DEBUG_ASSERT(!IsBoundLocked());
  DEBUG_ASSERT(target != nullptr);
  DEBUG_ASSERT(port_ != nullptr);
  target_ = target;
}

void ExceptionPort::SetTarget(const fbl::RefPtr<ProcessDispatcher>& target) {
  canary_.Assert();

  LTRACE_ENTRY_OBJ;
  Guard<fbl::Mutex> guard{&lock_};
  DEBUG_ASSERT_MSG(type_ == Type::DEBUGGER || type_ == Type::PROCESS, "unexpected type %d",
                   static_cast<int>(type_));
  DEBUG_ASSERT(!IsBoundLocked());
  DEBUG_ASSERT(target != nullptr);
  DEBUG_ASSERT(port_ != nullptr);
  target_ = target;
}

void ExceptionPort::SetTarget(const fbl::RefPtr<ThreadDispatcher>& target) {
  canary_.Assert();

  LTRACE_ENTRY_OBJ;
  Guard<fbl::Mutex> guard{&lock_};
  DEBUG_ASSERT_MSG(type_ == Type::THREAD, "unexpected type %d", static_cast<int>(type_));
  DEBUG_ASSERT(!IsBoundLocked());
  DEBUG_ASSERT(target != nullptr);
  DEBUG_ASSERT(port_ != nullptr);
  target_ = target;
}

// Called by PortDispatcher after unlinking us from its eport list.
void ExceptionPort::OnPortZeroHandles() {
  canary_.Assert();

  LTRACE_ENTRY_OBJ;
  Guard<fbl::Mutex> guard{&lock_};
  if (port_ == nullptr) {
    // Already unbound. This can happen when
    // PortDispatcher::on_zero_handles and a manual unbind (via
    // zx_task_bind_exception_port) race with each other.
    LTRACEF("already unbound\n");
    DEBUG_ASSERT(!IsBoundLocked());
    return;
  }

  // Unbind ourselves from our target if necessary. At the end of this
  // block, some thread (ours or another) will have called back into our
  // ::OnTargetUnbind method, cleaning up our target/port references. The
  // "other thread" case can happen if another thread manually unbinds after
  // we release the lock.
  if (!IsBoundLocked()) {
    // Created but never bound.
    guard.Release();
    // Simulate an unbinding to finish cleaning up.
    OnTargetUnbind();
  } else {
    switch (type_) {
      case Type::JOB:
      case Type::JOB_DEBUGGER: {
        DEBUG_ASSERT(target_ != nullptr);
        auto job = DownCastDispatcher<JobDispatcher>(&target_);
        DEBUG_ASSERT(job != nullptr);
        guard.Release();  // The target may call our ::OnTargetUnbind
        job->ResetExceptionPort(type_ == Type::JOB_DEBUGGER);
        break;
      }
      case Type::PROCESS:
      case Type::DEBUGGER: {
        DEBUG_ASSERT(target_ != nullptr);
        auto process = DownCastDispatcher<ProcessDispatcher>(&target_);
        DEBUG_ASSERT(process != nullptr);
        guard.Release();  // The target may call our ::OnTargetUnbind
        process->ResetExceptionPort(type_ == Type::DEBUGGER);
        break;
      }
      case Type::THREAD: {
        DEBUG_ASSERT(target_ != nullptr);
        auto thread = DownCastDispatcher<ThreadDispatcher>(&target_);
        DEBUG_ASSERT(thread != nullptr);
        guard.Release();  // The target may call our ::OnTargetUnbind
        thread->ResetExceptionPort();
        break;
      }
      default:
        PANIC("unexpected type %d", static_cast<int>(type_));
    }
  }
  // All cases must release the lock.
  DEBUG_ASSERT(!lock_.lock().IsHeld());

#if (LK_DEBUGLEVEL > 1)
  // The target should have called back into ::OnTargetUnbind by this point,
  // cleaning up our references.
  {
    Guard<fbl::Mutex> guard2{&lock_};
    DEBUG_ASSERT(port_ == nullptr);
    DEBUG_ASSERT(!IsBoundLocked());
  }
#endif  // if (LK_DEBUGLEVEL > 1)

  LTRACE_EXIT_OBJ;
}

void ExceptionPort::OnTargetUnbind() {
  canary_.Assert();

  LTRACE_ENTRY_OBJ;
  fbl::RefPtr<PortDispatcher> port;
  {
    Guard<fbl::Mutex> guard{&lock_};
    if (port_ == nullptr) {
      // Already unbound.
      // This could happen if ::OnPortZeroHandles releases the
      // lock and another thread immediately does a manual unbind
      // via zx_task_bind_exception_port.
      DEBUG_ASSERT(!IsBoundLocked());
      return;
    }
    // Clear port_, indicating that this ExceptionPort has been unbound.
    port_.swap(port);

    // Drop references to the target.
    // We may not have a target if the binding (Set*Target) never happened,
    // so don't require that we're bound.
    target_.reset();

    // Unlink ourselves from the PortDispatcher's list.
    // No-op if this method was ultimately called from
    // PortDispatcher:on_zero_handles (via ::OnPortZeroHandles).
    port->UnlinkExceptionPortEportLocked(this);
  }

  LTRACE_EXIT_OBJ;
}

bool ExceptionPort::PortMatches(const PortDispatcher* port, bool allow_null) {
  Guard<fbl::Mutex> guard{&lock_};
  return PortMatchesLocked(port, allow_null);
}

bool ExceptionPort::PortMatchesLocked(const PortDispatcher* port, bool allow_null) {
  return (allow_null && port_ == nullptr) || port_.get() == port;
}

zx_status_t ExceptionPort::SendPacketWorker(uint32_t type, zx_koid_t pid, zx_koid_t tid) {
  Guard<fbl::Mutex> guard{&lock_};
  LTRACEF("%s, type %u, pid %" PRIu64 ", tid %" PRIu64 "\n",
          port_ == nullptr ? "Not sending exception report on unbound port"
                           : "Sending exception report",
          type, pid, tid);
  if (port_ == nullptr) {
    // The port has been unbound.
    return ZX_ERR_PEER_CLOSED;
  }

  auto iopk = MakePacket(port_key_, type, pid, tid);
  if (!iopk)
    return ZX_ERR_NO_MEMORY;

  zx_status_t status = port_->Queue(iopk, 0, 0);
  if (status != ZX_OK) {
    iopk->Free();
  }
  return status;
}

zx_status_t ExceptionPort::SendPacket(ThreadDispatcher* thread, uint32_t type) {
  canary_.Assert();

  zx_koid_t pid = thread->process()->get_koid();
  zx_koid_t tid = thread->get_koid();
  return SendPacketWorker(type, pid, tid);
}

void ExceptionPort::BuildReport(zx_exception_report_t* report, uint32_t type) {
  memset(report, 0, sizeof(*report));
  report->header.size = sizeof(*report);
  report->header.type = type;
}

void ExceptionPort::BuildArchReport(zx_exception_report_t* report, uint32_t type,
                                    const arch_exception_context_t* context) {
  BuildReport(report, type);
  arch_fill_in_exception_context(context, report);
}

void ExceptionPort::OnThreadStartForDebugger(ThreadDispatcher* thread,
                                             const arch_exception_context_t* context) {
  canary_.Assert();

  DEBUG_ASSERT(type_ == Type::DEBUGGER);

  zx_koid_t pid = thread->process()->get_koid();
  zx_koid_t tid = thread->get_koid();
  LTRACEF("thread %" PRIu64 ".%" PRIu64 " started\n", pid, tid);

  zx_status_t status =
      dispatch_debug_exception(fbl::RefPtr<ExceptionPort>(this), ZX_EXCP_THREAD_STARTING, context);
  if (status != ZX_OK) {
    // Ignore any errors. There's nothing we can do here, and
    // we still want the thread to run. It's possible the thread was
    // killed (status == ZX_ERR_INTERNAL_INTR_KILLED), the kernel will kill
    // the thread shortly.
  }
}

void ExceptionPort::OnProcessStartForDebugger(ThreadDispatcher* thread,
                                              const arch_exception_context_t* context) {
  canary_.Assert();

  DEBUG_ASSERT(type_ == Type::JOB_DEBUGGER);

  zx_koid_t pid = thread->process()->get_koid();
  zx_koid_t tid = thread->get_koid();
  LTRACEF("process %" PRIu64 ".%" PRIu64 " started\n", pid, tid);

  zx_status_t status =
      dispatch_debug_exception(fbl::RefPtr<ExceptionPort>(this), ZX_EXCP_PROCESS_STARTING, context);
  if (status != ZX_OK) {
    // Ignore any errors. There's nothing we can do here, and
    // we still want the thread to run. It's possible the thread was
    // killed (status == ZX_ERR_INTERNAL_INTR_KILLED), the kernel will kill
    // the thread shortly.
  }
}

// This isn't called for every thread's destruction, only when a debugger
// is attached.

void ExceptionPort::OnThreadExitForDebugger(ThreadDispatcher* thread) {
  canary_.Assert();

  DEBUG_ASSERT(type_ == Type::DEBUGGER);

  zx_koid_t pid = thread->process()->get_koid();
  zx_koid_t tid = thread->get_koid();
  LTRACEF("thread %" PRIu64 ".%" PRIu64 " exited\n", pid, tid);

  // There is no iframe at the moment. We'll need one (or equivalent) if/when
  // we want to make $pc, $sp available.
  arch_exception_context_t context{};

  // N.B. If the process is exiting it will have killed all threads. That
  // means all threads get marked with THREAD_SIGNAL_KILL which means this
  // exchange will return immediately with ZX_ERR_INTERNAL_INTR_KILLED.
  zx_status_t status =
      dispatch_debug_exception(fbl::RefPtr<ExceptionPort>(this), ZX_EXCP_THREAD_EXITING, &context);
  if (status != ZX_OK) {
    // Ignore any errors, we still want the thread to continue exiting.
  }
}
