// 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 <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <trace.h>
#include <zircon/syscalls/object.h>

#include <arch/exception.h>
#include <fbl/auto_call.h>
#include <object/excp_port.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 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.
}
