Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Unified Diff: util/mach/exc_server_variants.cc

Issue 766193006: exc_server_variants: Templatize and use CompositeMachMessageServer (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review feedback Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « util/mach/exc_server_variants.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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(
« no previous file with comments | « util/mach/exc_server_variants.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698