// Copyright 2016 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 <arch.h>
#include <arch/exception.h>
#include <assert.h>
#include <err.h>
#include <fbl/auto_call.h>
#include <inttypes.h>
#include <stdio.h>
#include <trace.h>

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

#include <fbl/auto_call.h>
#include <zircon/syscalls/object.h>

#define LOCAL_TRACE 0
#define TRACE_EXCEPTIONS 1

static const char* excp_type_to_string(uint type) {
    switch (type) {
    case ZX_EXCP_FATAL_PAGE_FAULT:
        return "fatal page fault";
    case ZX_EXCP_UNDEFINED_INSTRUCTION:
        return "undefined instruction";
    case ZX_EXCP_GENERAL:
        return "general fault";
    case ZX_EXCP_SW_BREAKPOINT:
        return "software breakpoint";
    case ZX_EXCP_HW_BREAKPOINT:
        return "hardware breakpoint";
    case ZX_EXCP_UNALIGNED_ACCESS:
        return "alignment fault";
    case ZX_EXCP_POLICY_ERROR:
        return "policy error";
    case ZX_EXCP_PROCESS_STARTING:
        return "process starting";
    case ZX_EXCP_THREAD_STARTING:
        return "thread starting";
    case ZX_EXCP_THREAD_EXITING:
        return "thread exiting";
    default:
        return "unknown fault";
    }
}

// This isn't an "iterator" in the pure c++ sense. We don't need all that
// complexity. I just couldn't think of a better term.
//
// Exception ports are tried in the following order:
// - debugger
// - thread
// - thread channel
// - process
// - job (first owning job, then its parent job, and so on up to root job)
class ExceptionPortIterator final {
public:
    // All exception handler types, including both ports and channels.
    // TODO(ZX-3072): remove ports once everyone is switched to channels.
    enum class Type {
        NONE,
        JOB_DEBUGGER,
        JOB_DEBUGGER_CHANNEL,
        DEBUGGER,
        DEBUGGER_CHANNEL,
        THREAD,
        THREAD_CHANNEL,
        PROCESS,
        PROCESS_CHANNEL,
        JOB,
        JOB_CHANNEL
    };

    explicit ExceptionPortIterator(ThreadDispatcher* thread,
                                   fbl::RefPtr<ExceptionDispatcher> exception)
        : thread_(thread), exception_(ktl::move(exception)), previous_type_(Type::NONE) {}

    // Returns true with |eport| filled in if the caller should dispatch the
    // exception to the given exception port.
    // Returns true with empty |eport| and filled |channel_result| if the
    // exception was sent to a channel handler.
    // Returns false if there are no more to try.
    bool Next(fbl::RefPtr<ExceptionPort>* eport, zx_status_t* channel_result) {
        eport->reset(nullptr);
        bool sent_to_channel = false;

        while (true) {
            switch (previous_type_) {
                case Type::NONE:
                    *eport = thread_->process()->debugger_exception_port();
                    previous_type_ = Type::DEBUGGER;
                    break;
                case Type::DEBUGGER:
                    *channel_result = thread_->HandleException(
                        thread_->process()->exceptionate(Exceptionate::Type::kDebug),
                        exception_, &sent_to_channel);
                    previous_type_ = Type::DEBUGGER_CHANNEL;
                    break;
                case Type::DEBUGGER_CHANNEL:
                    *eport = thread_->exception_port();
                    previous_type_ = Type::THREAD;
                    break;
                case Type::THREAD:
                    *channel_result = thread_->HandleException(
                        thread_->exceptionate(), exception_, &sent_to_channel);
                    previous_type_ = Type::THREAD_CHANNEL;
                    break;
                case Type::THREAD_CHANNEL:
                    *eport = thread_->process()->exception_port();
                    previous_type_ = Type::PROCESS;
                    break;
                case Type::PROCESS:
                    *channel_result = thread_->HandleException(
                        thread_->process()->exceptionate(Exceptionate::Type::kStandard),
                        exception_, &sent_to_channel);
                    previous_type_ = Type::PROCESS_CHANNEL;
                    break;
                case Type::PROCESS_CHANNEL:
                    previous_job_ = thread_->process()->job();
                    *eport = previous_job_->exception_port();
                    previous_type_ = Type::JOB;
                    break;
                case Type::JOB:
                    *channel_result = thread_->HandleException(
                        previous_job_->exceptionate(Exceptionate::Type::kStandard),
                        exception_, &sent_to_channel);
                    previous_type_ = Type::JOB_CHANNEL;
                    break;
                case Type::JOB_CHANNEL:
                    previous_job_ = previous_job_->parent();
                    if (previous_job_) {
                        *eport = previous_job_->exception_port();
                    } else {
                        // Reached the root job and there was no handler.
                       return false;
                    }
                    previous_type_ = Type::JOB;
                    break;
                default:
                    ASSERT_MSG(0, "unexpected exception type %d",
                               static_cast<int>(previous_type_));
                    __UNREACHABLE;
            }

            // Only service one port or channel exception per call, not both.
            DEBUG_ASSERT(!(eport->get() && sent_to_channel));

            // Return to the caller once we find either a port to process or
            // a channel that was processed.
            if (eport->get() || sent_to_channel) {
                return true;
            }

        }
        __UNREACHABLE;
    }

private:
    ThreadDispatcher* thread_;
    fbl::RefPtr<ExceptionDispatcher> exception_;
    Type previous_type_;
    // Jobs are traversed up their hierarchy. This is the previous one.
    fbl::RefPtr<JobDispatcher> previous_job_;

    DISALLOW_COPY_ASSIGN_AND_MOVE(ExceptionPortIterator);
};

static zx_status_t try_exception_handler(fbl::RefPtr<ExceptionPort> eport,
                                         ThreadDispatcher* thread,
                                         const zx_exception_report_t* report,
                                         const arch_exception_context_t* arch_context,
                                         ThreadState::Exception* estatus) {
    LTRACEF("Trying exception port type %d\n", static_cast<int>(eport->type()));
    auto status = thread->ExceptionHandlerExchange(eport, report, arch_context, estatus);
    LTRACEF("ExceptionHandlerExchange returned status %d, estatus %d\n", status, static_cast<int>(*estatus));

    return status;
}

enum handler_status_t {
    // thread is to be resumed
    HS_RESUME,
    // thread was killed
    HS_KILLED,
    // exception not handled (process will be killed)
    HS_NOT_HANDLED
};

// Subroutine of dispatch_user_exception to simplify the code.
// One useful thing this does is guarantee ExceptionPortIterator is properly
// destructed.
// |*out_processed| is set to a boolean indicating if at least one
// handler processed the exception.
static handler_status_t exception_handler_worker(uint exception_type,
                                                 const arch_exception_context_t* context,
                                                 ThreadDispatcher* thread,
                                                 bool* out_processed) {
    *out_processed = false;

    zx_exception_report_t report;
    ExceptionPort::BuildArchReport(&report, exception_type, context);

    fbl::RefPtr<ExceptionDispatcher> exception = ExceptionDispatcher::Create(
        fbl::WrapRefPtr(thread), exception_type, &report, context);
    if (!exception) {
        // No memory to create the exception, we just have to drop it which
        // will kill the process.
        printf("KERN: failed to allocate memory for %s exception in user thread %lu.%lu\n",
               excp_type_to_string(exception_type), thread->process()->get_koid(),
               thread->get_koid());
        return HS_NOT_HANDLED;
    }

    // Most of the time we'll be holding the last reference to the exception
    // when this function exits, but if the task is killed we return HS_KILLED
    // without waiting for the handler which means someone may still have a
    // handle to the exception.
    //
    // For simplicity and to catch any unhandled status cases below, just clean
    // out the exception before returning no matter what.
    auto exception_cleaner = fbl::MakeAutoCall([&exception]() { exception->Clear(); });

    ExceptionPortIterator iter(thread, exception);
    fbl::RefPtr<ExceptionPort> eport;
    // This should always be overwritten, either by iter.Next() for channels
    // or try_exception_handler() for ports.
    zx_status_t status = ZX_ERR_INTERNAL;

    while (iter.Next(&eport, &status)) {
        // Initialize for paranoia's sake.
        ThreadState::Exception estatus = ThreadState::Exception::UNPROCESSED;
        if (eport) {
            status = try_exception_handler(eport, thread, &report, context, &estatus);
        } else {
            // Channels return a single status value, for now map this to the
            // existing port logic which combines resume/try_next into ZX_OK.
            if (status == ZX_OK) {
                estatus = ThreadState::Exception::RESUME;
            } else if (status == ZX_ERR_NEXT) {
                status = ZX_OK;
                estatus = ThreadState::Exception::TRY_NEXT;
            }
        }

        LTRACEF("handler returned %d/%d\n",
                static_cast<int>(status), static_cast<int>(estatus));
        switch (status) {
        case ZX_ERR_INTERNAL_INTR_KILLED:
            // thread was killed, probably with zx_task_kill
            return HS_KILLED;
        case ZX_OK:
            switch (estatus) {
            case ThreadState::Exception::TRY_NEXT:
                *out_processed = true;
                break;
            case ThreadState::Exception::RESUME:
                return HS_RESUME;
            default:
                ASSERT_MSG(0, "invalid exception status %d",
                           static_cast<int>(estatus));
                __UNREACHABLE;
            }
            break;
        default:
            // Instead of requiring exception processing to only return
            // specific kinds of errors (and thus requiring us to be updated
            // every time a change causes a new error to be returned), treat
            // all other errors as fatal. It's debatable whether to give the
            // next handler a try or immediately kill the task. By immediately
            // killing the task we bypass the root job exception handler,
            // but it feels safer.
            // TODO(ZX-2853): Are there times when we should try harder to
            // process the exception?
            // Print something to give the user a clue.
            printf("KERN: Error %d processing exception in user thread %lu.%lu\n",
                   status, thread->process()->get_koid(), thread->get_koid());
            // Still mark the exception as processed so that we don't trigger
            // later bare-bones crash reporting (TRACE_EXCEPTIONS).
            *out_processed = true;
            return HS_NOT_HANDLED;
        }
    }

    return HS_NOT_HANDLED;
}

// Dispatches an exception to the appropriate handler. Called by arch code
// when it cannot handle an exception.
//
// If we return ZX_OK, the caller is expected to resume the thread "as if"
// nothing happened, the handler is expected to have modified state such that
// resumption is possible.
//
// If we return ZX_ERR_BAD_STATE, the current thread is not a user thread
// (i.e., not associated with a ThreadDispatcher).
//
// Otherwise, we cause the current thread to exit and do not return at all.
//
// TODO(dje): Support unwinding from this exception and introducing a different
// exception?
zx_status_t dispatch_user_exception(uint exception_type,
                                    const arch_exception_context_t* context) {
    LTRACEF("type %u, context %p\n", exception_type, context);

    thread_t* lk_thread = get_current_thread();
    ThreadDispatcher* thread = lk_thread->user_thread;
    if (unlikely(!thread)) {
        // The current thread is not a user thread; bail.
        return ZX_ERR_BAD_STATE;
    }

    // From now until the exception is resolved the thread is in an exception.
    ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::EXCEPTION);

    arch_install_context_regs(lk_thread, context);
    bool processed;
    handler_status_t hstatus =
        exception_handler_worker(exception_type, context, thread, &processed);
    arch_remove_context_regs(lk_thread);

    switch (hstatus) {
        case HS_RESUME:
            return ZX_OK;
        case HS_KILLED:
            thread->Exit();
            __UNREACHABLE;
        case HS_NOT_HANDLED:
            break;
        default:
            ASSERT_MSG(0, "unexpected exception worker result %d", static_cast<int>(hstatus));
            __UNREACHABLE;
    }

    auto process = thread->process();

#if TRACE_EXCEPTIONS
    if (!processed) {
        // only print this if an exception handler wasn't involved
        // in handling the exception
        char pname[ZX_MAX_NAME_LEN];
        process->get_name(pname);
        char tname[ZX_MAX_NAME_LEN];
        thread->get_name(tname);
        printf("KERN: %s in user thread '%s' in process '%s'\n",
               excp_type_to_string(exception_type), tname, pname);

        arch_dump_exception_context(context);
    }
#endif

    // kill our process
    process->Kill(ZX_TASK_RETCODE_EXCEPTION_KILL);

    // exit
    thread->Exit();

    // should not get here
    panic("fell out of thread exit somehow!\n");
    __UNREACHABLE;
}

zx_status_t dispatch_debug_exception(fbl::RefPtr<ExceptionPort> eport,
                                     uint exception_type,
                                     const arch_exception_context_t* context) {
    LTRACEF("type %u, context %p\n", exception_type, context);

    thread_t* lk_thread = get_current_thread();
    ThreadDispatcher* thread = lk_thread->user_thread;
    // This function can only be called on behalf of user threads.
    DEBUG_ASSERT(thread);

    // From now until the exception is resolved the thread is in an exception.
    ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::EXCEPTION);

    arch_install_context_regs(lk_thread, context);
    auto ac = fbl::MakeAutoCall([&lk_thread]() {
        arch_remove_context_regs(lk_thread);
    });

    zx_exception_report_t report;
    ExceptionPort::BuildArchReport(&report, exception_type, context);

    ThreadState::Exception estatus;
    return thread->ExceptionHandlerExchange(eport, &report, context, &estatus);
    // We can ignore |estatus| here (TRY_NEXT/RESUME) as they're not used.
}
