// Copyright 2014 The Crashpad Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "util/mach/exc_server_variants.h"

#include <Availability.h>
#include <string.h>

#include <algorithm>
#include <iterator>
#include <vector>

#include "build/build_config.h"
#include "util/mac/mac_util.h"
#include "util/mach/composite_mach_message_server.h"
#include "util/mach/exc.h"
#include "util/mach/excServer.h"
#include "util/mach/exception_behaviors.h"
#include "util/mach/mach_exc.h"
#include "util/mach/mach_excServer.h"
#include "util/mach/mach_message.h"

namespace crashpad {

namespace {

// Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with
// the exc subsystem.
struct ExcTraits {
  using ExceptionCode = exception_data_type_t;

  using RequestUnion = __RequestUnion__exc_subsystem;
  using ReplyUnion = __ReplyUnion__exc_subsystem;

  using ExceptionRaiseRequest = __Request__exception_raise_t;
  using ExceptionRaiseStateRequest = __Request__exception_raise_state_t;
  using ExceptionRaiseStateIdentityRequest =
      __Request__exception_raise_state_identity_t;

  using ExceptionRaiseReply = __Reply__exception_raise_t;
  using ExceptionRaiseStateReply = __Reply__exception_raise_state_t;
  using ExceptionRaiseStateIdentityReply =
      __Reply__exception_raise_state_identity_t;

  // The MIG-generated __MIG_check__Request__*() functions are not declared as
  // accepting const data, but they could have been because they in fact do not
  // modify the data.

  static kern_return_t MIGCheckRequestExceptionRaise(
      const ExceptionRaiseRequest* in_request) {
    return __MIG_check__Request__exception_raise_t(
        const_cast<ExceptionRaiseRequest*>(in_request));
  }

  static kern_return_t MIGCheckRequestExceptionRaiseState(
      const ExceptionRaiseStateRequest* in_request,
      const ExceptionRaiseStateRequest** in_request_1) {
    return __MIG_check__Request__exception_raise_state_t(
        const_cast<ExceptionRaiseStateRequest*>(in_request),
        const_cast<ExceptionRaiseStateRequest**>(in_request_1));
  }

  static kern_return_t MIGCheckRequestExceptionRaiseStateIdentity(
      const ExceptionRaiseStateIdentityRequest* in_request,
      const ExceptionRaiseStateIdentityRequest** in_request_1) {
    return __MIG_check__Request__exception_raise_state_identity_t(
        const_cast<ExceptionRaiseStateIdentityRequest*>(in_request),
        const_cast<ExceptionRaiseStateIdentityRequest**>(in_request_1));
  }

  // There are no predefined constants for these.
  static const mach_msg_id_t kMachMessageIDExceptionRaise = 2401;
  static const mach_msg_id_t kMachMessageIDExceptionRaiseState = 2402;
  static const mach_msg_id_t kMachMessageIDExceptionRaiseStateIdentity = 2403;

  static const exception_behavior_t kExceptionBehavior = 0;
};

// Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with
// the mach_exc subsystem.
struct MachExcTraits {
  using ExceptionCode = mach_exception_data_type_t;

  using RequestUnion = __RequestUnion__mach_exc_subsystem;
  using ReplyUnion = __ReplyUnion__mach_exc_subsystem;

  using ExceptionRaiseRequest = __Request__mach_exception_raise_t;
  using ExceptionRaiseStateRequest = __Request__mach_exception_raise_state_t;
  using ExceptionRaiseStateIdentityRequest =
      __Request__mach_exception_raise_state_identity_t;

  using ExceptionRaiseReply = __Reply__mach_exception_raise_t;
  using ExceptionRaiseStateReply = __Reply__mach_exception_raise_state_t;
  using ExceptionRaiseStateIdentityReply =
      __Reply__mach_exception_raise_state_identity_t;

  // The MIG-generated __MIG_check__Request__*() functions are not declared as
  // accepting const data, but they could have been because they in fact do not
  // modify the data.

  static kern_return_t MIGCheckRequestExceptionRaise(
      const ExceptionRaiseRequest* in_request) {
    return __MIG_check__Request__mach_exception_raise_t(
        const_cast<ExceptionRaiseRequest*>(in_request));
  }

  static kern_return_t MIGCheckRequestExceptionRaiseState(
      const ExceptionRaiseStateRequest* in_request,
      const ExceptionRaiseStateRequest** in_request_1) {
    return __MIG_check__Request__mach_exception_raise_state_t(
        const_cast<ExceptionRaiseStateRequest*>(in_request),
        const_cast<ExceptionRaiseStateRequest**>(in_request_1));
  }

  static kern_return_t MIGCheckRequestExceptionRaiseStateIdentity(
      const ExceptionRaiseStateIdentityRequest* in_request,
      const ExceptionRaiseStateIdentityRequest** in_request_1) {
    return __MIG_check__Request__mach_exception_raise_state_identity_t(
        const_cast<ExceptionRaiseStateIdentityRequest*>(in_request),
        const_cast<ExceptionRaiseStateIdentityRequest**>(in_request_1));
  }

  // There are no predefined constants for these.
  static const mach_msg_id_t kMachMessageIDExceptionRaise = 2405;
  static const mach_msg_id_t kMachMessageIDExceptionRaiseState = 2406;
  static const mach_msg_id_t kMachMessageIDExceptionRaiseStateIdentity = 2407;

  static const exception_behavior_t kExceptionBehavior = MACH_EXCEPTION_CODES;
};

//! \brief A server interface for the `exc` or `mach_exc` Mach subsystems.
template <typename Traits>
class ExcServer : public MachMessageServer::Interface {
 public:
  //! \brief An interface that the different request messages that are a part of
  //!     the `exc` or `mach_exc` Mach subsystems can be dispatched to.
  class Interface {
   public:
    //! \brief Handles exceptions raised by `exception_raise()` or
    //!     `mach_exception_raise()`.
    //!
    //! This behaves equivalently to a `catch_exception_raise()` function used
    //! with `exc_server()`, or a `catch_mach_exception_raise()` function used
    //! with `mach_exc_server()`.
    //!
    //! \param[in] trailer The trailer received with the request message.
    //! \param[out] destroy_request `true` if the request message is to be
    //!     destroyed even when this method returns success. See
    //!     MachMessageServer::Interface.
    virtual kern_return_t CatchExceptionRaise(
        exception_handler_t exception_port,
        thread_t thread,
        task_t task,
        exception_type_t exception,
        const typename Traits::ExceptionCode* code,
        mach_msg_type_number_t code_count,
        const mach_msg_trailer_t* trailer,
        bool* destroy_request) = 0;

    //! \brief Handles exceptions raised by `exception_raise_state()` or
    //!     `mach_exception_raise_state()`.
    //!
    //! This behaves equivalently to a `catch_exception_raise_state()` function
    //! used with `exc_server()`, or a `catch_mach_exception_raise_state()`
    //! function used with `mach_exc_server()`.
    //!
    //! There is no \a destroy_request parameter because, unlike
    //! CatchExceptionRaise() and CatchExceptionRaiseStateIdentity(), the
    //! request message is not complex (it does not carry the \a thread or \a
    //! task port rights) and thus there is nothing to destroy.
    //!
    //! \param[in] trailer The trailer received with the request message.
    virtual kern_return_t CatchExceptionRaiseState(
        exception_handler_t exception_port,
        exception_type_t exception,
        const typename Traits::ExceptionCode* code,
        mach_msg_type_number_t code_count,
        thread_state_flavor_t* flavor,
        ConstThreadState old_state,
        mach_msg_type_number_t old_state_count,
        thread_state_t new_state,
        mach_msg_type_number_t* new_state_count,
        const mach_msg_trailer_t* trailer) = 0;

    //! \brief Handles exceptions raised by `exception_raise_state_identity()`
    //!     or `mach_exception_raise_state_identity()`.
    //!
    //! This behaves equivalently to a `catch_exception_raise_state_identity()`
    //! function used with `exc_server()`, or a
    //! `catch_mach_exception_raise_state_identity()` function used with
    //! `mach_exc_server()`.
    //!
    //! \param[in] trailer The trailer received with the request message.
    //! \param[out] destroy_request `true` if the request message is to be
    //!     destroyed even when this method returns success. See
    //!     MachMessageServer::Interface.
    virtual kern_return_t CatchExceptionRaiseStateIdentity(
        exception_handler_t exception_port,
        thread_t thread,
        task_t task,
        exception_type_t exception,
        const typename Traits::ExceptionCode* code,
        mach_msg_type_number_t code_count,
        thread_state_flavor_t* flavor,
        ConstThreadState old_state,
        mach_msg_type_number_t old_state_count,
        thread_state_t new_state,
        mach_msg_type_number_t* new_state_count,
        const mach_msg_trailer_t* trailer,
        bool* destroy_request) = 0;

   protected:
    ~Interface() {}
  };

  //! \brief Constructs an object of this class.
  //!
  //! \param[in] interface The interface to dispatch requests to. Weak.
  explicit ExcServer(Interface* interface)
      : MachMessageServer::Interface(), interface_(interface) {}

  ExcServer(const ExcServer&) = delete;
  ExcServer& operator=(const ExcServer&) = delete;

  // MachMessageServer::Interface:

  bool MachMessageServerFunction(const mach_msg_header_t* in_header,
                                 mach_msg_header_t* out_header,
                                 bool* destroy_complex_request) override;

  std::set<mach_msg_id_t> MachMessageServerRequestIDs() override {
    constexpr mach_msg_id_t request_ids[] = {
        Traits::kMachMessageIDExceptionRaise,
        Traits::kMachMessageIDExceptionRaiseState,
        Traits::kMachMessageIDExceptionRaiseStateIdentity,
    };
    return std::set<mach_msg_id_t>(&request_ids[0],
                                   &request_ids[std::size(request_ids)]);
  }

  mach_msg_size_t MachMessageServerRequestSize() override {
    return sizeof(typename Traits::RequestUnion);
  }

  mach_msg_size_t MachMessageServerReplySize() override {
    return sizeof(typename Traits::ReplyUnion);
  }

 private:
  Interface* interface_;  // weak
};

template <typename Traits>
bool ExcServer<Traits>::MachMessageServerFunction(
    const mach_msg_header_t* in_header,
    mach_msg_header_t* out_header,
    bool* destroy_complex_request) {
  PrepareMIGReplyFromRequest(in_header, out_header);

  const mach_msg_trailer_t* in_trailer =
      MachMessageTrailerFromHeader(in_header);

  switch (in_header->msgh_id) {
    case Traits::kMachMessageIDExceptionRaise: {
      // exception_raise(), catch_exception_raise(), mach_exception_raise(),
      // catch_mach_exception_raise().
      using Request = typename Traits::ExceptionRaiseRequest;
      const Request* in_request = reinterpret_cast<const Request*>(in_header);
      kern_return_t kr = Traits::MIGCheckRequestExceptionRaise(in_request);
      if (kr != MACH_MSG_SUCCESS) {
        SetMIGReplyError(out_header, kr);
        return true;
      }

      using Reply = typename Traits::ExceptionRaiseReply;
      Reply* out_reply = reinterpret_cast<Reply*>(out_header);
      out_reply->RetCode =
          interface_->CatchExceptionRaise(in_header->msgh_local_port,
                                          in_request->thread.name,
                                          in_request->task.name,
                                          in_request->exception,
                                          in_request->code,
                                          in_request->codeCnt,
                                          in_trailer,
                                          destroy_complex_request);
      if (out_reply->RetCode != KERN_SUCCESS) {
        return true;
      }

      out_header->msgh_size = sizeof(*out_reply);
      return true;
    }

    case Traits::kMachMessageIDExceptionRaiseState: {
      // exception_raise_state(), catch_exception_raise_state(),
      // mach_exception_raise_state(), catch_mach_exception_raise_state().
      using Request = typename Traits::ExceptionRaiseStateRequest;
      const Request* in_request = reinterpret_cast<const Request*>(in_header);

      // in_request_1 is used for the portion of the request after the codes,
      // which in theory can be variable-length. The check function will set it.
      const Request* in_request_1;
      kern_return_t kr =
          Traits::MIGCheckRequestExceptionRaiseState(in_request, &in_request_1);
      if (kr != MACH_MSG_SUCCESS) {
        SetMIGReplyError(out_header, kr);
        return true;
      }

      using Reply = typename Traits::ExceptionRaiseStateReply;
      Reply* out_reply = reinterpret_cast<Reply*>(out_header);
      out_reply->flavor = in_request_1->flavor;
      out_reply->new_stateCnt = std::size(out_reply->new_state);
      out_reply->RetCode =
          interface_->CatchExceptionRaiseState(in_header->msgh_local_port,
                                               in_request->exception,
                                               in_request->code,
                                               in_request->codeCnt,
                                               &out_reply->flavor,
                                               in_request_1->old_state,
                                               in_request_1->old_stateCnt,
                                               out_reply->new_state,
                                               &out_reply->new_stateCnt,
                                               in_trailer);
      if (out_reply->RetCode != KERN_SUCCESS) {
        return true;
      }

      out_header->msgh_size =
          sizeof(*out_reply) - sizeof(out_reply->new_state) +
          sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
      return true;
    }

    case Traits::kMachMessageIDExceptionRaiseStateIdentity: {
      // exception_raise_state_identity(),
      // catch_exception_raise_state_identity(),
      // mach_exception_raise_state_identity(),
      // catch_mach_exception_raise_state_identity().
      using Request = typename Traits::ExceptionRaiseStateIdentityRequest;
      const Request* in_request = reinterpret_cast<const Request*>(in_header);

      // in_request_1 is used for the portion of the request after the codes,
      // which in theory can be variable-length. The check function will set it.
      const Request* in_request_1;
      kern_return_t kr = Traits::MIGCheckRequestExceptionRaiseStateIdentity(
          in_request, &in_request_1);
      if (kr != MACH_MSG_SUCCESS) {
        SetMIGReplyError(out_header, kr);
        return true;
      }

      using Reply = typename Traits::ExceptionRaiseStateIdentityReply;
      Reply* out_reply = reinterpret_cast<Reply*>(out_header);
      out_reply->flavor = in_request_1->flavor;
      out_reply->new_stateCnt = std::size(out_reply->new_state);
      out_reply->RetCode = interface_->CatchExceptionRaiseStateIdentity(
          in_header->msgh_local_port,
          in_request->thread.name,
          in_request->task.name,
          in_request->exception,
          in_request->code,
          in_request->codeCnt,
          &out_reply->flavor,
          in_request_1->old_state,
          in_request_1->old_stateCnt,
          out_reply->new_state,
          &out_reply->new_stateCnt,
          in_trailer,
          destroy_complex_request);
      if (out_reply->RetCode != KERN_SUCCESS) {
        return true;
      }

      out_header->msgh_size =
          sizeof(*out_reply) - sizeof(out_reply->new_state) +
          sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
      return true;
    }

    default: {
      SetMIGReplyError(out_header, MIG_BAD_ID);
      return false;
    }
  }
}

//! \brief A server interface for the `exc` or `mach_exc` Mach subsystems,
//!     simplified to have only a single interface method needing
//!     implementation.
template <typename Traits>
class SimplifiedExcServer final : public ExcServer<Traits>,
                                  public ExcServer<Traits>::Interface {
 public:
  //! \brief An interface that the different request messages that are a part of
  //!     the `exc` or `mach_exc` Mach subsystems can be dispatched to.
  class Interface {
   public:
    //! \brief Handles exceptions raised by `exception_raise()`,
    //!     `exception_raise_state()`, and `exception_raise_state_identity()`;
    //!     or `mach_exception_raise()`, `mach_exception_raise_state()`, and
    //!     `mach_exception_raise_state_identity()`.
    //!
    //! For convenience in implementation, these different “behaviors” of
    //! exception messages are all mapped to a single interface method. The
    //! exception’s original “behavior” is specified in the \a behavior
    //! parameter. Only parameters that were supplied in the request message
    //! are populated, other parameters are set to reasonable default values.
    //!
    //! The meanings of most parameters are identical to that of
    //! ExcServer<>::Interface::CatchExceptionRaiseStateIdentity().
    //!
    //! \param[in] behavior `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or
    //!     `EXCEPTION_STATE_IDENTITY`, identifying which exception request
    //!     message was processed and thus which other parameters are valid.
    //!     When used with the `mach_exc` subsystem, `MACH_EXCEPTION_CODES` will
    //!     be ORed in to this parameter.
    virtual kern_return_t CatchException(
        exception_behavior_t behavior,
        exception_handler_t exception_port,
        thread_t thread,
        task_t task,
        exception_type_t exception,
        const typename Traits::ExceptionCode* code,
        mach_msg_type_number_t code_count,
        thread_state_flavor_t* flavor,
        ConstThreadState old_state,
        mach_msg_type_number_t old_state_count,
        thread_state_t new_state,
        mach_msg_type_number_t* new_state_count,
        const mach_msg_trailer_t* trailer,
        bool* destroy_complex_request) = 0;

   protected:
    ~Interface() {}
  };

  //! \brief Constructs an object of this class.
  //!
  //! \param[in] interface The interface to dispatch requests to. Weak.
  explicit SimplifiedExcServer(Interface* interface)
      : ExcServer<Traits>(this),
        ExcServer<Traits>::Interface(),
        interface_(interface) {}

  SimplifiedExcServer(const SimplifiedExcServer&) = delete;
  SimplifiedExcServer& operator=(const SimplifiedExcServer&) = delete;

  // ExcServer::Interface:

  kern_return_t CatchExceptionRaise(exception_handler_t exception_port,
                                    thread_t thread,
                                    task_t task,
                                    exception_type_t exception,
                                    const typename Traits::ExceptionCode* code,
                                    mach_msg_type_number_t code_count,
                                    const mach_msg_trailer_t* trailer,
                                    bool* destroy_request) override {
    thread_state_flavor_t flavor = THREAD_STATE_NONE;
    mach_msg_type_number_t new_state_count = 0;
    return interface_->CatchException(
        Traits::kExceptionBehavior | EXCEPTION_DEFAULT,
        exception_port,
        thread,
        task,
        exception,
        code_count ? code : nullptr,
        code_count,
        &flavor,
        nullptr,
        0,
        nullptr,
        &new_state_count,
        trailer,
        destroy_request);
  }

  kern_return_t CatchExceptionRaiseState(
      exception_handler_t exception_port,
      exception_type_t exception,
      const typename Traits::ExceptionCode* code,
      mach_msg_type_number_t code_count,
      thread_state_flavor_t* flavor,
      ConstThreadState old_state,
      mach_msg_type_number_t old_state_count,
      thread_state_t new_state,
      mach_msg_type_number_t* new_state_count,
      const mach_msg_trailer_t* trailer) override {
    bool destroy_complex_request = false;
    return interface_->CatchException(
        Traits::kExceptionBehavior | EXCEPTION_STATE,
        exception_port,
        THREAD_NULL,
        TASK_NULL,
        exception,
        code_count ? code : nullptr,
        code_count,
        flavor,
        old_state_count ? old_state : nullptr,
        old_state_count,
        new_state_count ? new_state : nullptr,
        new_state_count,
        trailer,
        &destroy_complex_request);
  }

  kern_return_t CatchExceptionRaiseStateIdentity(
      exception_handler_t exception_port,
      thread_t thread,
      task_t task,
      exception_type_t exception,
      const typename Traits::ExceptionCode* code,
      mach_msg_type_number_t code_count,
      thread_state_flavor_t* flavor,
      ConstThreadState old_state,
      mach_msg_type_number_t old_state_count,
      thread_state_t new_state,
      mach_msg_type_number_t* new_state_count,
      const mach_msg_trailer_t* trailer,
      bool* destroy_request) override {
    return interface_->CatchException(
        Traits::kExceptionBehavior | EXCEPTION_STATE_IDENTITY,
        exception_port,
        thread,
        task,
        exception,
        code_count ? code : nullptr,
        code_count,
        flavor,
        old_state_count ? old_state : nullptr,
        old_state_count,
        new_state_count ? new_state : nullptr,
        new_state_count,
        trailer,
        destroy_request);
  }

 private:
  Interface* interface_;  // weak
};

}  // namespace

namespace internal {

class UniversalMachExcServerImpl final
    : public CompositeMachMessageServer,
      public SimplifiedExcServer<ExcTraits>::Interface,
      public SimplifiedExcServer<MachExcTraits>::Interface {
 public:
  explicit UniversalMachExcServerImpl(
      UniversalMachExcServer::Interface* interface)
      : CompositeMachMessageServer(),
        SimplifiedExcServer<ExcTraits>::Interface(),
        SimplifiedExcServer<MachExcTraits>::Interface(),
        exc_server_(this),
        mach_exc_server_(this),
        interface_(interface) {
    AddHandler(&exc_server_);
    AddHandler(&mach_exc_server_);
  }

  UniversalMachExcServerImpl(const UniversalMachExcServerImpl&) = delete;
  UniversalMachExcServerImpl& operator=(const UniversalMachExcServerImpl&) =
      delete;

  ~UniversalMachExcServerImpl() {}

  // SimplifiedExcServer<ExcTraits>::Interface:
  kern_return_t CatchException(exception_behavior_t behavior,
                               exception_handler_t exception_port,
                               thread_t thread,
                               task_t task,
                               exception_type_t exception,
                               const exception_data_type_t* code,
                               mach_msg_type_number_t code_count,
                               thread_state_flavor_t* flavor,
                               ConstThreadState old_state,
                               mach_msg_type_number_t old_state_count,
                               thread_state_t new_state,
                               mach_msg_type_number_t* new_state_count,
                               const mach_msg_trailer_t* trailer,
                               bool* destroy_complex_request) {
    std::vector<mach_exception_data_type_t> mach_codes;
    mach_codes.reserve(code_count);
    for (size_t index = 0; index < code_count; ++index) {
      mach_codes.push_back(code[index]);
    }

    return interface_->CatchMachException(behavior,
                                          exception_port,
                                          thread,
                                          task,
                                          exception,
                                          code_count ? &mach_codes[0] : nullptr,
                                          code_count,
                                          flavor,
                                          old_state_count ? old_state : nullptr,
                                          old_state_count,
                                          new_state_count ? new_state : nullptr,
                                          new_state_count,
                                          trailer,
                                          destroy_complex_request);
  }

  // SimplifiedExcServer<MachExcTraits>::Interface:
  kern_return_t CatchException(exception_behavior_t behavior,
                               exception_handler_t exception_port,
                               thread_t thread,
                               task_t task,
                               exception_type_t exception,
                               const mach_exception_data_type_t* code,
                               mach_msg_type_number_t code_count,
                               thread_state_flavor_t* flavor,
                               ConstThreadState old_state,
                               mach_msg_type_number_t old_state_count,
                               thread_state_t new_state,
                               mach_msg_type_number_t* new_state_count,
                               const mach_msg_trailer_t* trailer,
                               bool* destroy_complex_request) {
    return interface_->CatchMachException(behavior,
                                          exception_port,
                                          thread,
                                          task,
                                          exception,
                                          code_count ? code : nullptr,
                                          code_count,
                                          flavor,
                                          old_state_count ? old_state : nullptr,
                                          old_state_count,
                                          new_state_count ? new_state : nullptr,
                                          new_state_count,
                                          trailer,
                                          destroy_complex_request);
  }

 private:
  SimplifiedExcServer<ExcTraits> exc_server_;
  SimplifiedExcServer<MachExcTraits> mach_exc_server_;
  UniversalMachExcServer::Interface* interface_;  // weak
};

}  // namespace internal

UniversalMachExcServer::UniversalMachExcServer(
    UniversalMachExcServer::Interface* interface)
    : MachMessageServer::Interface(),
      impl_(new internal::UniversalMachExcServerImpl(interface)) {
}

UniversalMachExcServer::~UniversalMachExcServer() {
}

bool UniversalMachExcServer::MachMessageServerFunction(
    const mach_msg_header_t* in_header,
    mach_msg_header_t* out_header,
    bool* destroy_complex_request) {
  return impl_->MachMessageServerFunction(
      in_header, out_header, destroy_complex_request);
}

std::set<mach_msg_id_t> UniversalMachExcServer::MachMessageServerRequestIDs() {
  return impl_->MachMessageServerRequestIDs();
}

mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() {
  return impl_->MachMessageServerRequestSize();
}

mach_msg_size_t UniversalMachExcServer::MachMessageServerReplySize() {
  return impl_->MachMessageServerReplySize();
}

kern_return_t ExcServerSuccessfulReturnValue(exception_type_t exception,
                                             exception_behavior_t behavior,
                                             bool set_thread_state) {
  if (exception == EXC_CRASH
#if BUILDFLAG(IS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_11
      && MacOSVersionNumber() >= 10'11'00
#endif
  ) {
    return KERN_SUCCESS;
  }

  if (!set_thread_state && ExceptionBehaviorHasState(behavior)) {
    return MACH_RCV_PORT_DIED;
  }

  return KERN_SUCCESS;
}

void ExcServerCopyState(exception_behavior_t behavior,
                        ConstThreadState old_state,
                        mach_msg_type_number_t old_state_count,
                        thread_state_t new_state,
                        mach_msg_type_number_t* new_state_count) {
  if (ExceptionBehaviorHasState(behavior)) {
    *new_state_count = std::min(old_state_count, *new_state_count);
    memcpy(new_state, old_state, *new_state_count * sizeof(old_state[0]));
  }
}

}  // namespace crashpad
