// 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 <arch/exception.h>

#include <object/job_dispatcher.h>
#include <object/port_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.h>

#include <fbl/alloc_checker.h>

#include <trace.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, fbl::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);
    port_->LinkExceptionPort(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();

    // TODO(ZX-988): Add a way to mark specific ports as unbinding quietly
    // when auto-unbinding.
    static const bool default_quietness = false;

    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, default_quietness);
                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, default_quietness);
                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(default_quietness);
                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();
    }
    // It should actually be safe to hold our lock while calling into
    // the PortDispatcher, but there's no reason to.

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

    LTRACE_EXIT_OBJ;
}

bool ExceptionPort::PortMatches(const PortDispatcher *port, bool allow_null) {
    Guard<fbl::Mutex> guard{&lock_};
    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* arch_context) {
    BuildReport(report, type);
    arch_fill_in_exception_context(arch_context, report);
}

void ExceptionPort::OnThreadStartForDebugger(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 " started\n", pid, tid);

    zx_exception_report_t report;
    BuildReport(&report, ZX_EXCP_THREAD_STARTING);
    arch_exception_context_t context;
    // There is no iframe at the moment. We'll need one (or equivalent) if/when
    // we want to make $pc, $sp available.
    memset(&context, 0, sizeof(context));
    ThreadState::Exception estatus;
    auto status = thread->ExceptionHandlerExchange(fbl::RefPtr<ExceptionPort>(this), &report, &context, &estatus);
    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) {
    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_exception_report_t report;
    BuildReport(&report, ZX_EXCP_PROCESS_STARTING);
    arch_exception_context_t context;
    // There is no iframe at the moment. We'll need one (or equivalent) if/when
    // we want to make $pc, $sp available.
    memset(&context, 0, sizeof(context));
    ThreadState::Exception estatus;
    auto status = thread->ExceptionHandlerExchange(fbl::RefPtr<ExceptionPort>(this), &report, &context, &estatus);
    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);

    zx_exception_report_t report;
    BuildReport(&report, ZX_EXCP_THREAD_EXITING);
    arch_exception_context_t context;
    // There is no iframe at the moment. We'll need one (or equivalent) if/when
    // we want to make $pc, $sp available.
    memset(&context, 0, sizeof(context));
    ThreadState::Exception estatus;
    // 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.
    auto status = thread->ExceptionHandlerExchange(fbl::RefPtr<ExceptionPort>(this), &report, &context, &estatus);
    if (status != ZX_OK) {
        // Ignore any errors, we still want the thread to continue exiting.
    }
}
