Chromium Code Reviews| 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..c0ffc8d87d538aa8a7beacd107118a681244b21a |
| --- /dev/null |
| +++ b/util/mach/exc_server_variants.h |
| @@ -0,0 +1,421 @@ |
| +// 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. |
| + |
| +//! \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()`. |
| + 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; |
|
Robert Sesek
2014/09/10 16:44:41
No destroy_request?
Mark Mentovai
2014/09/10 20:12:56
rsesek wrote:
|
| + |
| + //! \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()`. |
| + 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, |
|
Robert Sesek
2014/09/10 16:44:41
Do you really need to present all of these interfa
Mark Mentovai
2014/09/10 20:12:56
rsesek wrote:
|
| + 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 |
| +}; |
| + |
| +//! \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 SimplifiedExcServer::Interface, |
| + public 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; |
| + |
| + // 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: |
| + SimplifiedExcServer exc_server_; |
| + SimplifiedMachExcServer mach_exc_server_; |
| +}; |
| + |
| +} // namespace crashpad |
| + |
| +#endif // CRASHPAD_UTIL_MACH_EXC_SERVER_VARIANTS_H_ |