Index: util/mach/exc_server_variants.cc |
diff --git a/util/mach/exc_server_variants.cc b/util/mach/exc_server_variants.cc |
index 7dbe553f3a5e75d4d5a9ffc86fb0d310941a6f4f..99875a849c50bb86f81606db92d181e4d8d84249 100644 |
--- a/util/mach/exc_server_variants.cc |
+++ b/util/mach/exc_server_variants.cc |
@@ -18,6 +18,7 @@ |
#include <vector> |
#include "base/logging.h" |
+#include "util/mach/composite_mach_message_server.h" |
#include "util/mach/exc.h" |
#include "util/mach/exception_behaviors.h" |
#include "util/mach/excServer.h" |
@@ -117,100 +118,260 @@ kern_return_t catch_mach_exception_raise_state_identity( |
} // extern "C" |
+namespace crashpad { |
+ |
namespace { |
-// There are no predefined constants for these. |
-enum MachMessageID : mach_msg_id_t { |
- kMachMessageIDExceptionRaise = 2401, |
- kMachMessageIDExceptionRaiseState = 2402, |
- kMachMessageIDExceptionRaiseStateIdentity = 2403, |
- kMachMessageIDMachExceptionRaise = 2405, |
- kMachMessageIDMachExceptionRaiseState = 2406, |
- kMachMessageIDMachExceptionRaiseStateIdentity = 2407, |
+// 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) { |
+ using Request = __Request__exception_raise_state_t; |
+ 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; |
}; |
-// 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. These wrapper functions are provided to bridge the const gap |
-// between the code in this file, which is const-correct and treats request |
-// message data as const, and those generated functions. |
- |
-kern_return_t MIGCheckRequestExceptionRaise( |
- const __Request__exception_raise_t* in_request) { |
- using Request = __Request__exception_raise_t; |
- return __MIG_check__Request__exception_raise_t( |
- const_cast<Request*>(in_request)); |
-} |
+// Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with |
+// the mach_exc subsystem. |
+struct MachExcTraits { |
+ using ExceptionCode = mach_exception_data_type_t; |
-kern_return_t MIGCheckRequestExceptionRaiseState( |
- const __Request__exception_raise_state_t* in_request, |
- const __Request__exception_raise_state_t** in_request_1) { |
- using Request = __Request__exception_raise_state_t; |
- return __MIG_check__Request__exception_raise_state_t( |
- const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); |
-} |
+ using RequestUnion = __RequestUnion__mach_exc_subsystem; |
+ using ReplyUnion = __ReplyUnion__mach_exc_subsystem; |
-kern_return_t MIGCheckRequestExceptionRaiseStateIdentity( |
- const __Request__exception_raise_state_identity_t* in_request, |
- const __Request__exception_raise_state_identity_t** in_request_1) { |
- using Request = __Request__exception_raise_state_identity_t; |
- return __MIG_check__Request__exception_raise_state_identity_t( |
- const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); |
-} |
+ using ExceptionRaiseRequest = __Request__mach_exception_raise_t; |
+ using ExceptionRaiseStateRequest = __Request__mach_exception_raise_state_t; |
+ using ExceptionRaiseStateIdentityRequest = |
+ __Request__mach_exception_raise_state_identity_t; |
-kern_return_t MIGCheckRequestMachExceptionRaise( |
- const __Request__mach_exception_raise_t* in_request) { |
- using Request = __Request__mach_exception_raise_t; |
- return __MIG_check__Request__mach_exception_raise_t( |
- const_cast<Request*>(in_request)); |
-} |
+ using ExceptionRaiseReply = __Reply__mach_exception_raise_t; |
+ using ExceptionRaiseStateReply = __Reply__mach_exception_raise_state_t; |
+ using ExceptionRaiseStateIdentityReply = |
+ __Reply__mach_exception_raise_state_identity_t; |
-kern_return_t MIGCheckRequestMachExceptionRaiseState( |
- const __Request__mach_exception_raise_state_t* in_request, |
- const __Request__mach_exception_raise_state_t** in_request_1) { |
- using Request = __Request__mach_exception_raise_state_t; |
- return __MIG_check__Request__mach_exception_raise_state_t( |
- const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); |
-} |
+ // 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. |
-kern_return_t MIGCheckRequestMachExceptionRaiseStateIdentity( |
- const __Request__mach_exception_raise_state_identity_t* in_request, |
- const __Request__mach_exception_raise_state_identity_t** in_request_1) { |
- using Request = __Request__mach_exception_raise_state_identity_t; |
- return __MIG_check__Request__mach_exception_raise_state_identity_t( |
- const_cast<Request*>(in_request), const_cast<Request**>(in_request_1)); |
-} |
+ static kern_return_t MIGCheckRequestExceptionRaise( |
+ const ExceptionRaiseRequest* in_request) { |
+ return __MIG_check__Request__mach_exception_raise_t( |
+ const_cast<ExceptionRaiseRequest*>(in_request)); |
+ } |
-} // namespace |
+ static kern_return_t MIGCheckRequestExceptionRaiseState( |
+ const ExceptionRaiseStateRequest* in_request, |
+ const ExceptionRaiseStateRequest** in_request_1) { |
+ using Request = __Request__exception_raise_state_t; |
+ return __MIG_check__Request__mach_exception_raise_state_t( |
+ const_cast<ExceptionRaiseStateRequest*>(in_request), |
+ const_cast<ExceptionRaiseStateRequest**>(in_request_1)); |
+ } |
-namespace crashpad { |
-namespace internal { |
+ 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)); |
+ } |
-ExcServer::ExcServer(ExcServer::Interface* interface) |
- : MachMessageServer::Interface(), |
- interface_(interface) { |
-} |
+ // 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; |
-bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header, |
- mach_msg_header_t* out_header, |
- bool* destroy_complex_request) { |
+ 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, |
+ 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, |
+ 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, |
+ 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, |
+ 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) {} |
+ |
+ // 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 { |
+ const mach_msg_id_t request_ids[] = { |
+ Traits::kMachMessageIDExceptionRaise, |
+ Traits::kMachMessageIDExceptionRaiseState, |
+ Traits::kMachMessageIDExceptionRaiseStateIdentity, |
+ }; |
+ return std::set<mach_msg_id_t>(&request_ids[0], |
+ &request_ids[arraysize(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 |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ExcServer); |
+}; |
+ |
+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 kMachMessageIDExceptionRaise: { |
- // exception_raise(), catch_exception_raise(). |
- using Request = __Request__exception_raise_t; |
+ 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 = MIGCheckRequestExceptionRaise(in_request); |
+ kern_return_t kr = Traits::MIGCheckRequestExceptionRaise(in_request); |
if (kr != MACH_MSG_SUCCESS) { |
SetMIGReplyError(out_header, kr); |
return true; |
} |
- using Reply = __Reply__exception_raise_t; |
+ using Reply = typename Traits::ExceptionRaiseReply; |
Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
out_reply->RetCode = |
interface_->CatchExceptionRaise(in_header->msgh_local_port, |
@@ -229,22 +390,23 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header, |
return true; |
} |
- case kMachMessageIDExceptionRaiseState: { |
- // exception_raise_state(), catch_exception_raise_state(). |
- using Request = __Request__exception_raise_state_t; |
+ 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 = |
- MIGCheckRequestExceptionRaiseState(in_request, &in_request_1); |
+ Traits::MIGCheckRequestExceptionRaiseState(in_request, &in_request_1); |
if (kr != MACH_MSG_SUCCESS) { |
SetMIGReplyError(out_header, kr); |
return true; |
} |
- using Reply = __Reply__exception_raise_state_t; |
+ using Reply = typename Traits::ExceptionRaiseStateReply; |
Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
out_reply->flavor = in_request_1->flavor; |
out_reply->new_stateCnt = arraysize(out_reply->new_state); |
@@ -269,23 +431,25 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header, |
return true; |
} |
- case kMachMessageIDExceptionRaiseStateIdentity: { |
+ case Traits::kMachMessageIDExceptionRaiseStateIdentity: { |
// exception_raise_state_identity(), |
- // catch_exception_raise_state_identity(). |
- using Request = __Request__exception_raise_state_identity_t; |
+ // 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 = |
- MIGCheckRequestExceptionRaiseStateIdentity(in_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 = __Reply__exception_raise_state_identity_t; |
+ using Reply = typename Traits::ExceptionRaiseStateIdentityReply; |
Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
out_reply->flavor = in_request_1->flavor; |
out_reply->new_stateCnt = arraysize(out_reply->new_state); |
@@ -318,484 +482,287 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header, |
return false; |
} |
-std::set<mach_msg_id_t> ExcServer::MachMessageServerRequestIDs() { |
- const mach_msg_id_t request_ids[] = { |
- kMachMessageIDExceptionRaise, |
- kMachMessageIDExceptionRaiseState, |
- kMachMessageIDExceptionRaiseStateIdentity |
+//! \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, |
+ 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, |
+ const mach_msg_trailer_t* trailer, |
+ bool* destroy_complex_request) = 0; |
+ |
+ protected: |
+ ~Interface() {} |
}; |
- return std::set<mach_msg_id_t>( |
- &request_ids[0], &request_ids[arraysize(request_ids)]); |
-} |
-mach_msg_size_t ExcServer::MachMessageServerRequestSize() { |
- return sizeof(__RequestUnion__exc_subsystem); |
-} |
+ //! \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) {} |
-mach_msg_size_t ExcServer::MachMessageServerReplySize() { |
- return sizeof(__ReplyUnion__exc_subsystem); |
-} |
+ // ExcServer::Interface: |
-MachExcServer::MachExcServer(MachExcServer::Interface* interface) |
- : MachMessageServer::Interface(), |
- interface_(interface) { |
-} |
- |
-bool MachExcServer::MachMessageServerFunction( |
- const mach_msg_header_t* in_header, |
- mach_msg_header_t* out_header, |
- bool* destroy_complex_request) { |
- PrepareMIGReplyFromRequest(in_header, out_header); |
+ 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); |
+ } |
- const mach_msg_trailer_t* in_trailer = |
- MachMessageTrailerFromHeader(in_header); |
+ 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, |
+ 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, |
+ 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); |
+ } |
- switch (in_header->msgh_id) { |
- case kMachMessageIDMachExceptionRaise: { |
- // mach_exception_raise(), catch_mach_exception_raise(). |
- using Request = __Request__mach_exception_raise_t; |
- const Request* in_request = reinterpret_cast<const Request*>(in_header); |
- kern_return_t kr = MIGCheckRequestMachExceptionRaise(in_request); |
- if (kr != MACH_MSG_SUCCESS) { |
- SetMIGReplyError(out_header, kr); |
- return true; |
- } |
+ 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, |
+ 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, |
+ 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); |
+ } |
- using Reply = __Reply__mach_exception_raise_t; |
- Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
- out_reply->RetCode = |
- interface_->CatchMachExceptionRaise(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; |
- } |
+ private: |
+ Interface* interface_; // weak |
- out_header->msgh_size = sizeof(*out_reply); |
- return true; |
- } |
+ DISALLOW_COPY_AND_ASSIGN(SimplifiedExcServer); |
+}; |
- case kMachMessageIDMachExceptionRaiseState: { |
- // mach_exception_raise_state(), catch_mach_exception_raise_state(). |
- using Request = __Request__mach_exception_raise_state_t; |
- const Request* in_request = reinterpret_cast<const Request*>(in_header); |
+} // namespace |
- // 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 = |
- MIGCheckRequestMachExceptionRaiseState(in_request, &in_request_1); |
- if (kr != MACH_MSG_SUCCESS) { |
- SetMIGReplyError(out_header, kr); |
- return true; |
- } |
+namespace internal { |
- using Reply = __Reply__mach_exception_raise_state_t; |
- Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
- out_reply->flavor = in_request_1->flavor; |
- out_reply->new_stateCnt = arraysize(out_reply->new_state); |
- out_reply->RetCode = |
- interface_->CatchMachExceptionRaiseState(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; |
- } |
+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_); |
+ } |
- out_header->msgh_size = |
- sizeof(*out_reply) - sizeof(out_reply->new_state) + |
- sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; |
- return true; |
+ ~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, |
+ 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, |
+ 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]); |
} |
- case kMachMessageIDMachExceptionRaiseStateIdentity: { |
- // mach_exception_raise_state_identity(), |
- // catch_mach_exception_raise_state_identity(). |
- using Request = __Request__mach_exception_raise_state_identity_t; |
- 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 = MIGCheckRequestMachExceptionRaiseStateIdentity( |
- in_request, &in_request_1); |
- if (kr != MACH_MSG_SUCCESS) { |
- SetMIGReplyError(out_header, kr); |
- return true; |
- } |
- |
- using Reply = __Reply__mach_exception_raise_state_identity_t; |
- Reply* out_reply = reinterpret_cast<Reply*>(out_header); |
- out_reply->flavor = in_request_1->flavor; |
- out_reply->new_stateCnt = arraysize(out_reply->new_state); |
- out_reply->RetCode = interface_->CatchMachExceptionRaiseStateIdentity( |
- 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; |
- } |
+ 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); |
} |
- SetMIGReplyError(out_header, MIG_BAD_ID); |
- return false; |
-} |
- |
-std::set<mach_msg_id_t> MachExcServer::MachMessageServerRequestIDs() { |
- const mach_msg_id_t request_ids[] = { |
- kMachMessageIDMachExceptionRaise, |
- kMachMessageIDMachExceptionRaiseState, |
- kMachMessageIDMachExceptionRaiseStateIdentity |
- }; |
- return std::set<mach_msg_id_t>( |
- &request_ids[0], &request_ids[arraysize(request_ids)]); |
-} |
- |
-mach_msg_size_t MachExcServer::MachMessageServerRequestSize() { |
- return sizeof(__RequestUnion__mach_exc_subsystem); |
-} |
- |
-mach_msg_size_t MachExcServer::MachMessageServerReplySize() { |
- return sizeof(__ReplyUnion__mach_exc_subsystem); |
-} |
- |
-SimplifiedExcServer::SimplifiedExcServer( |
- SimplifiedExcServer::Interface* interface) |
- : ExcServer(this), |
- ExcServer::Interface(), |
- interface_(interface) { |
-} |
- |
-kern_return_t SimplifiedExcServer::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, |
- const mach_msg_trailer_t* trailer, |
- bool* destroy_request) { |
- thread_state_flavor_t flavor = THREAD_STATE_NONE; |
- mach_msg_type_number_t new_state_count = 0; |
- return interface_->CatchException(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 SimplifiedExcServer::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, |
- const mach_msg_trailer_t* trailer) { |
- bool destroy_complex_request = false; |
- return interface_->CatchException(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 SimplifiedExcServer::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, |
- const mach_msg_trailer_t* trailer, |
- bool* destroy_request) { |
- return interface_->CatchException(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); |
-} |
- |
-SimplifiedMachExcServer::SimplifiedMachExcServer( |
- SimplifiedMachExcServer::Interface* interface) |
- : MachExcServer(this), |
- MachExcServer::Interface(), |
- interface_(interface) { |
-} |
+ // 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, |
+ 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, |
+ 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); |
+ } |
-kern_return_t SimplifiedMachExcServer::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, |
- const mach_msg_trailer_t* trailer, |
- bool* destroy_request) { |
- thread_state_flavor_t flavor = THREAD_STATE_NONE; |
- mach_msg_type_number_t new_state_count = 0; |
- return interface_->CatchMachException( |
- EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, |
- exception_port, |
- thread, |
- task, |
- exception, |
- code_count ? code : nullptr, |
- code_count, |
- &flavor, |
- nullptr, |
- 0, |
- nullptr, |
- &new_state_count, |
- trailer, |
- destroy_request); |
-} |
+ private: |
+ SimplifiedExcServer<ExcTraits> exc_server_; |
+ SimplifiedExcServer<MachExcTraits> mach_exc_server_; |
+ UniversalMachExcServer::Interface* interface_; // weak |
-kern_return_t SimplifiedMachExcServer::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, |
- const mach_msg_trailer_t* trailer) { |
- bool destroy_complex_request = false; |
- return interface_->CatchMachException(EXCEPTION_STATE | MACH_EXCEPTION_CODES, |
- 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 SimplifiedMachExcServer::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, |
- const mach_msg_trailer_t* trailer, |
- bool* destroy_request) { |
- return interface_->CatchMachException( |
- EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, |
- 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); |
-} |
+ DISALLOW_COPY_AND_ASSIGN(UniversalMachExcServerImpl); |
+}; |
} // namespace internal |
UniversalMachExcServer::UniversalMachExcServer( |
UniversalMachExcServer::Interface* interface) |
: MachMessageServer::Interface(), |
- internal::SimplifiedExcServer::Interface(), |
- internal::SimplifiedMachExcServer::Interface(), |
- exc_server_(this), |
- mach_exc_server_(this), |
- interface_(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) { |
- switch (in_header->msgh_id) { |
- case kMachMessageIDMachExceptionRaise: |
- case kMachMessageIDMachExceptionRaiseState: |
- case kMachMessageIDMachExceptionRaiseStateIdentity: |
- return mach_exc_server_.MachMessageServerFunction( |
- in_header, out_header, destroy_complex_request); |
- case kMachMessageIDExceptionRaise: |
- case kMachMessageIDExceptionRaiseState: |
- case kMachMessageIDExceptionRaiseStateIdentity: |
- return exc_server_.MachMessageServerFunction( |
- in_header, out_header, destroy_complex_request); |
- } |
- |
- // Do what the MIG-generated server routines do when they can’t dispatch a |
- // message. |
- PrepareMIGReplyFromRequest(in_header, out_header); |
- SetMIGReplyError(out_header, MIG_BAD_ID); |
- return false; |
+ return impl_->MachMessageServerFunction( |
+ in_header, out_header, destroy_complex_request); |
} |
std::set<mach_msg_id_t> UniversalMachExcServer::MachMessageServerRequestIDs() { |
- std::set<mach_msg_id_t> request_ids = |
- exc_server_.MachMessageServerRequestIDs(); |
- |
- std::set<mach_msg_id_t> mach_exc_request_ids = |
- mach_exc_server_.MachMessageServerRequestIDs(); |
- request_ids.insert(mach_exc_request_ids.begin(), mach_exc_request_ids.end()); |
- |
- return request_ids; |
+ return impl_->MachMessageServerRequestIDs(); |
} |
mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() { |
- return std::max(mach_exc_server_.MachMessageServerRequestSize(), |
- exc_server_.MachMessageServerRequestSize()); |
+ return impl_->MachMessageServerRequestSize(); |
} |
mach_msg_size_t UniversalMachExcServer::MachMessageServerReplySize() { |
- return std::max(mach_exc_server_.MachMessageServerReplySize(), |
- exc_server_.MachMessageServerReplySize()); |
-} |
- |
-kern_return_t UniversalMachExcServer::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, |
- 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); |
-} |
- |
-kern_return_t UniversalMachExcServer::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, |
- 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); |
+ return impl_->MachMessageServerReplySize(); |
} |
exception_type_t ExcCrashRecoverOriginalException( |