// 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 <assert.h>
#include <inttypes.h>
#include <lib/fit/defer.h>
#include <stdio.h>
#include <trace.h>
#include <zircon/errors.h>
#include <zircon/syscalls/object.h>
#include <zircon/types.h>

#include <arch/exception.h>
#include <object/exception_dispatcher.h>
#include <object/job_dispatcher.h>
#include <object/process_dispatcher.h>
#include <object/thread_dispatcher.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 handlers are tried in the following order:
// - debugger
// - thread
// - process
// - debugger (in dealing with a second-chance exception)
// - job (first owning job, then its parent job, and so on up to root job)
class ExceptionHandlerIterator final {
 public:
  explicit ExceptionHandlerIterator(ThreadDispatcher* thread,
                                    fbl::RefPtr<ExceptionDispatcher> exception)
      : thread_(thread), exception_(ktl::move(exception)) {}

  // Sends the exception to the next registered handler, starting with
  // ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER (the process debug channel) on the first
  // call.
  //
  // Returns true with and fills |result| if the exception was sent to a
  // handler, or returns false if there are no more to try. Do not call this
  // function again after it returns false.
  bool Next(zx_status_t* result) {
    bool sent = false;

    while (true) {
      // This state may change during the handling of the debugger exception
      // channel. Accordingly, we check its value before the next round of
      // handling to be sure of the proper sequencing.
      bool second_chance = exception_->IsSecondChance();

      switch (next_type_) {
        case ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER:
          *result = thread_->HandleException(
              thread_->process()->exceptionate(Exceptionate::Type::kDebug), exception_, &sent);
          if (second_chance) {
            next_type_ = ZX_EXCEPTION_CHANNEL_TYPE_JOB;
            next_job_ = thread_->process()->job();
          } else {
            next_type_ = ZX_EXCEPTION_CHANNEL_TYPE_THREAD;
          }
          break;
        case ZX_EXCEPTION_CHANNEL_TYPE_THREAD:
          *result = thread_->HandleException(thread_->exceptionate(), exception_, &sent);
          next_type_ = ZX_EXCEPTION_CHANNEL_TYPE_PROCESS;
          break;
        case ZX_EXCEPTION_CHANNEL_TYPE_PROCESS:
          *result = thread_->HandleException(
              thread_->process()->exceptionate(Exceptionate::Type::kStandard), exception_, &sent);

          if (second_chance) {
            next_type_ = ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER;
          } else {
            next_type_ = ZX_EXCEPTION_CHANNEL_TYPE_JOB;
            next_job_ = thread_->process()->job();
          }
          break;
        case ZX_EXCEPTION_CHANNEL_TYPE_JOB:
          if (next_job_ == nullptr) {
            // Reached the root job and there was no handler.
            return false;
          }
          *result = thread_->HandleException(next_job_->exceptionate(Exceptionate::Type::kStandard),
                                             exception_, &sent);
          next_job_ = next_job_->parent();
          break;
        default:
          ASSERT_MSG(0, "unexpected exception type %u", next_type_);
          __UNREACHABLE;
      }

      // Return to the caller once a handler was activated.
      if (sent) {
        return true;
      }
    }
    __UNREACHABLE;
  }

 private:
  ThreadDispatcher* thread_;
  fbl::RefPtr<ExceptionDispatcher> exception_;
  uint32_t next_type_ = ZX_EXCEPTION_CHANNEL_TYPE_DEBUGGER;
  fbl::RefPtr<JobDispatcher> next_job_;

  DISALLOW_COPY_ASSIGN_AND_MOVE(ExceptionHandlerIterator);
};

// Subroutine of dispatch_user_exception to simplify the code.
// One useful thing this does is guarantee ExceptionHandlerIterator is properly
// destructed.
//
// |*out_processed| is set to a boolean indicating if at least one
// handler processed the exception.
//
// Returns:
//   ZX_OK if the thread has been resumed.
//   ZX_ERR_NEXT if we ran out of handlers before the thread resumed.
//   ZX_ERR_INTERNAL_INTR_KILLED if the thread was killed.
//   ZX_ERR_NO_MEMORY on allocation failure (TODO(fxbug.dev/33566): remove this case)
static zx_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 = ExceptionDispatcher::BuildArchReport(exception_type, *context);

  fbl::RefPtr<ExceptionDispatcher> exception =
      ExceptionDispatcher::Create(fbl::RefPtr(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 ZX_ERR_NO_MEMORY;
  }

  // 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 = fit::defer([&exception]() { exception->Clear(); });

  ExceptionHandlerIterator iter(thread, exception);
  zx_status_t status = ZX_ERR_NEXT;
  while (iter.Next(&status)) {
    LTRACEF("handler returned %d\n", status);

    // ZX_ERR_NEXT means the handler wants to pass it up to the next in the
    // chain, keep looping but mark that at least one handler saw the exception.
    if (status == ZX_ERR_NEXT) {
      *out_processed = true;
      continue;
    }

    // ZX_ERR_STOP means the handler wants to kill the thread.
    if (status == ZX_ERR_STOP) {
      *out_processed = true;
      DEBUG_ASSERT(thread == ThreadDispatcher::GetCurrent());
      ThreadDispatcher::KillCurrent();
      return ZX_ERR_INTERNAL_INTR_KILLED;
    }

    // Anything other than ZX_ERR_NEXT means we're done.
    return status;
  }

  if (status != ZX_ERR_NEXT) {
    // If the iterator returned false, but status got changed from ZX_ERR_NEXT, then this means it
    // attempted to send to a handler, but the sending process failed. We still have no way to
    // handle the exception but we can at least make noise in the debuglog.
    printf(
        "KERN: Failed to deliver %s exception to exception handler in user thread %lu.%lu with "
        "status: %d\n",
        excp_type_to_string(exception_type), thread->process()->get_koid(), thread->get_koid(),
        status);
  }

  // If we got here we ran out of handlers and nobody resumed the thread.
  return ZX_ERR_NEXT;
}

// 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* arch_context) {
  LTRACEF("type %u, context %p\n", exception_type, arch_context);

  ThreadDispatcher* thread = ThreadDispatcher::GetCurrent();
  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);

  bool processed = false;
  zx_status_t status;
  {
    // We're about to handle the exception.  Use a |ScopedThreadExceptionContext| to make the
    // thread's user register state available to debuggers and exception handlers while the thread
    // is "in exception".
    ScopedThreadExceptionContext context(arch_context);
    status = exception_handler_worker(exception_type, arch_context, thread, &processed);
  }

  if (status == ZX_OK) {
    return ZX_OK;
  }

  // If the thread wasn't resumed or explicitly killed, kill the whole process.
  if (status != ZX_ERR_INTERNAL_INTR_KILLED) {
    auto process = thread->process();

    char pname[ZX_MAX_NAME_LEN];
    process->get_name(pname);

#if TRACE_EXCEPTIONS
    // If no handlers even saw the exception, dump some info. Normally at least
    // crashsvc will handle the exception and make a smarter decision about what
    // to do with it, but in case it doesn't, dump some info to the kernel logs.
    if (!processed) {
      char tname[ZX_MAX_NAME_LEN];
      thread->get_name(tname);
      printf("KERN: exception_handler_worker returned %d\n", status);
      printf("KERN: %s in user thread '%s' in process '%s'\n", excp_type_to_string(exception_type),
             tname, pname);

      arch_dump_exception_context(arch_context);
    }
#endif

    printf("KERN: terminating process '%s' (%lu)\n", pname, process->get_koid());
    process->Kill(ZX_TASK_RETCODE_EXCEPTION_KILL);
  }

  // Either the current thread or its whole process was killed, we can now stop
  // it from running.
  ThreadDispatcher::ExitCurrent();
  panic("fell out of thread exit somehow!\n");
  __UNREACHABLE;
}
