| Index: util/mach/exc_server_variants.h
|
| diff --git a/util/mach/exc_server_variants.h b/util/mach/exc_server_variants.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..08e770aabbe395918c468d836abd5209579f346c
|
| --- /dev/null
|
| +++ b/util/mach/exc_server_variants.h
|
| @@ -0,0 +1,436 @@
|
| +// Copyright 2014 The Crashpad Authors. All rights reserved.
|
| +//
|
| +// 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.
|
| +
|
| +#ifndef CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_
|
| +#define CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_
|
| +
|
| +#include <mach/mach.h>
|
| +
|
| +#include "util/mach/mach_message_server.h"
|
| +
|
| +namespace crashpad {
|
| +
|
| +// Routines to provide a single unified front-end to the interfaces in
|
| +// <mach/exc.defs> and <mach/mach_exc.defs>. The two interfaces are identical,
|
| +// except that the latter allows for 64-bit exception codes, and is requested by
|
| +// setting the MACH_EXCEPTION_CODES behavior bit associated with an exception
|
| +// port.
|
| +
|
| +namespace internal {
|
| +
|
| +//! \brief A server interface for the `exc` Mach subsystem.
|
| +class ExcServer : public MachMessageServer::Interface {
|
| + public:
|
| + //! \brief An interface that the different request messages that are a part of
|
| + //! the `exc` Mach subsystem can be dispatched to.
|
| + class Interface {
|
| + public:
|
| + //! \brief Handles exceptions raised by `exception_raise()`.
|
| + //!
|
| + //! This behaves equivalently to a `catch_exception_raise()` function used
|
| + //! with `exc_server()`.
|
| + //!
|
| + //! \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 exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + bool* destroy_request) = 0;
|
| +
|
| + //! \brief Handles exceptions raised by `exception_raise_state()`.
|
| + //!
|
| + //! This behaves equivalently to a `catch_exception_raise_state()` function
|
| + //! used with `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.
|
| + virtual kern_return_t CatchExceptionRaiseState(
|
| + exception_handler_t exception_port,
|
| + exception_type_t exception,
|
| + const exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count) = 0;
|
| +
|
| + //! \brief Handles exceptions raised by `exception_raise_state_identity()`.
|
| + //!
|
| + //! This behaves equivalently to a `catch_exception_raise_state_identity()`
|
| + //! function used with `exc_server()`.
|
| + //!
|
| + //! \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 exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_request) = 0;
|
| +
|
| + protected:
|
| + ~Interface() {}
|
| + };
|
| +
|
| + explicit ExcServer(Interface* interface);
|
| +
|
| + // MachMessageServer::Interface:
|
| +
|
| + virtual bool MachMessageServerFunction(
|
| + mach_msg_header_t* in_header,
|
| + mach_msg_header_t* out_header,
|
| + bool* destroy_complex_request) override;
|
| +
|
| + virtual mach_msg_size_t MachMessageServerRequestSize() override;
|
| + virtual mach_msg_size_t MachMessageServerReplySize() override;
|
| +
|
| + private:
|
| + Interface* interface_; // weak
|
| +};
|
| +
|
| +//! \brief A server interface for the `mach_exc` Mach subsystem.
|
| +class MachExcServer : public MachMessageServer::Interface {
|
| + public:
|
| + //! \brief An interface that the different request messages that are a part of
|
| + //! the `mach_exc` Mach subsystem can be dispatched to.
|
| + class Interface {
|
| + public:
|
| + //! \brief Handles exceptions raised by `mach_exception_raise()`.
|
| + //!
|
| + //! This behaves equivalently to a `catch_mach_exception_raise()` function
|
| + //! used with `mach_exc_server()`.
|
| + //!
|
| + //! \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 CatchMachExceptionRaise(
|
| + 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,
|
| + bool* destroy_request) = 0;
|
| +
|
| + //! \brief Handles exceptions raised by `mach_exception_raise_state()`.
|
| + //!
|
| + //! This behaves equivalently to a `catch_mach_exception_raise_state()`
|
| + //! function used with `mach_exc_server()`.
|
| + //!
|
| + //! There is no \a destroy_request parameter because, unlike
|
| + //! CatchMachExceptionRaise() and CatchMachExceptionRaiseStateIdentity(),
|
| + //! 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.
|
| + virtual kern_return_t CatchMachExceptionRaiseState(
|
| + exception_handler_t exception_port,
|
| + exception_type_t exception,
|
| + const mach_exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count) = 0;
|
| +
|
| + //! \brief Handles exceptions raised by
|
| + //! `mach_exception_raise_state_identity()`.
|
| + //!
|
| + //! This behaves equivalently to a
|
| + //! `catch_mach_exception_raise_state_identity()` function used with
|
| + //! `mach_exc_server()`.
|
| + //!
|
| + //! \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 CatchMachExceptionRaiseStateIdentity(
|
| + 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,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_request) = 0;
|
| +
|
| + protected:
|
| + ~Interface() {}
|
| + };
|
| +
|
| + explicit MachExcServer(Interface* interface);
|
| +
|
| + // MachMessageServer::Interface:
|
| +
|
| + virtual bool MachMessageServerFunction(
|
| + mach_msg_header_t* in_header,
|
| + mach_msg_header_t* out_header,
|
| + bool* destroy_complex_request) override;
|
| +
|
| + virtual mach_msg_size_t MachMessageServerRequestSize() override;
|
| + virtual mach_msg_size_t MachMessageServerReplySize() override;
|
| +
|
| + private:
|
| + Interface* interface_; // weak
|
| +};
|
| +
|
| +//! \brief A server interface for the `exc` Mach subsystem, simplified to have
|
| +//! only a single interface method needing implementation.
|
| +class SimplifiedExcServer : public ExcServer, public ExcServer::Interface {
|
| + public:
|
| + //! \brief An interface that the different request messages that are a part of
|
| + //! the `exc` Mach subsystem can be dispatched to.
|
| + class Interface {
|
| + public:
|
| + //! \brief Handles exceptions raised by `exception_raise()`,
|
| + //! `exception_raise_state()`, and `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.
|
| + 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 exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_complex_request) = 0;
|
| +
|
| + protected:
|
| + ~Interface() {}
|
| + };
|
| +
|
| + explicit SimplifiedExcServer(Interface* interface);
|
| +
|
| + // ExcServer::Interface:
|
| +
|
| + virtual kern_return_t CatchExceptionRaise(
|
| + 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,
|
| + bool* destroy_request) override;
|
| + virtual kern_return_t CatchExceptionRaiseState(
|
| + exception_handler_t exception_port,
|
| + exception_type_t exception,
|
| + const exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count) override;
|
| + virtual kern_return_t CatchExceptionRaiseStateIdentity(
|
| + 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,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_request) override;
|
| +
|
| + private:
|
| + Interface* interface_; // weak
|
| +};
|
| +
|
| +//! \brief A server interface for the `mach_exc` Mach subsystem, simplified to
|
| +//! have only a single interface method needing implementation.
|
| +class SimplifiedMachExcServer : public MachExcServer,
|
| + public MachExcServer::Interface {
|
| + public:
|
| + //! \brief An interface that the different request messages that are a part of
|
| + //! the `mach_exc` Mach subsystem can be dispatched to.
|
| + class Interface {
|
| + public:
|
| + //! \brief Handles exceptions raised by `mach_exception_raise()`,
|
| + //! `mach_exception_raise_state()`, and
|
| + //! `mach_exception_raise_state_identity()`.
|
| + //!
|
| + //! When used with UniversalMachExcServer, this also handles exceptions
|
| + //! raised by `exception_raise()`, `exception_raise_state()`, and
|
| + //! `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
|
| + //! MachExcServer::Interface::CatchMachExceptionRaiseStateIdentity().
|
| + //!
|
| + //! \param[in] behavior `MACH_EXCEPTION_CODES | EXCEPTION_DEFAULT`,
|
| + //! `MACH_EXCEPTION_CODES | EXCEPTION_STATE`, or
|
| + //! `MACH_EXCEPTION_CODES | EXCEPTION_STATE_IDENTITY`, identifying which
|
| + //! exception request message was processed and thus which other
|
| + //! parameters are valid. When used with UniversalMachExcServer, \a
|
| + //! behavior can also be `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or
|
| + //! `EXCEPTION_STATE_IDENTITY`.
|
| + virtual kern_return_t CatchMachException(
|
| + 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,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_complex_request) = 0;
|
| +
|
| + protected:
|
| + ~Interface() {}
|
| + };
|
| +
|
| + explicit SimplifiedMachExcServer(Interface* interface);
|
| +
|
| + // MachExcServer::Interface:
|
| +
|
| + virtual kern_return_t CatchMachExceptionRaise(
|
| + 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,
|
| + bool* destroy_request) override;
|
| + virtual kern_return_t CatchMachExceptionRaiseState(
|
| + exception_handler_t exception_port,
|
| + exception_type_t exception,
|
| + const mach_exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count) override;
|
| + virtual kern_return_t CatchMachExceptionRaiseStateIdentity(
|
| + 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,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_request) override;
|
| +
|
| + private:
|
| + Interface* interface_; // weak
|
| +};
|
| +
|
| +} // namespace internal
|
| +
|
| +//! \brief A server interface for the `exc` and `mach_exc` Mach subsystems,
|
| +//! unified to handle exceptions delivered to either subsystem, and
|
| +//! simplified to have only a single interface method needing
|
| +//! implementation.
|
| +//!
|
| +//! UniversalMachExcServer operates by translating messages received in the
|
| +//! `exc` subsystem to a variant that is compatible with the `mach_exc`
|
| +//! subsystem. This involves changing the format of \a code, the exception code
|
| +//! field, from `exception_data_type_t` to `mach_exception_data_type_t`.
|
| +//! This is achieved by implementing SimplifiedExcServer::Interface and having
|
| +//! it forward translated messages to SimplifiedMachExcServer::Interface, which
|
| +//! is left unimplemented here so that users of this class can provide their own
|
| +//! implementations.
|
| +class UniversalMachExcServer
|
| + : public MachMessageServer::Interface,
|
| + public internal::SimplifiedExcServer::Interface,
|
| + public internal::SimplifiedMachExcServer::Interface {
|
| + public:
|
| + UniversalMachExcServer();
|
| +
|
| + // MachMessageServer::Interface:
|
| +
|
| + virtual bool MachMessageServerFunction(
|
| + mach_msg_header_t* in_header,
|
| + mach_msg_header_t* out_header,
|
| + bool* destroy_complex_request) override;
|
| +
|
| + virtual mach_msg_size_t MachMessageServerRequestSize() override;
|
| + virtual mach_msg_size_t MachMessageServerReplySize() override;
|
| +
|
| + // internal::SimplifiedExcServer::Interface:
|
| +
|
| + 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 exception_data_type_t* code,
|
| + mach_msg_type_number_t code_count,
|
| + thread_state_flavor_t* flavor,
|
| + const natural_t* old_state,
|
| + mach_msg_type_number_t old_state_count,
|
| + thread_state_t new_state,
|
| + mach_msg_type_number_t* new_state_count,
|
| + bool* destroy_complex_request) override;
|
| +
|
| + private:
|
| + internal::SimplifiedExcServer exc_server_;
|
| + internal::SimplifiedMachExcServer mach_exc_server_;
|
| +};
|
| +
|
| +} // namespace crashpad
|
| +
|
| +#endif // CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_
|
|
|