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

Unified Diff: third_party/crashpad/crashpad/util/mach/exc_server_variants.cc

Issue 1505213004: Copy Crashpad into the Chrome tree instead of importing it via DEPS (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments, update README.chromium Created 5 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
Index: third_party/crashpad/crashpad/util/mach/exc_server_variants.cc
diff --git a/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc b/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc
new file mode 100644
index 0000000000000000000000000000000000000000..c5a74a3b16bdaf9d33852935be10303a23b94125
--- /dev/null
+++ b/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc
@@ -0,0 +1,801 @@
+// 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.
+
+#include "util/mach/exc_server_variants.h"
+
+#include <AvailabilityMacros.h>
+#include <string.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "base/logging.h"
+#include "util/mac/mac_util.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"
+#include "util/mach/mach_exc.h"
+#include "util/mach/mach_excServer.h"
+#include "util/mach/mach_message.h"
+
+extern "C" {
+
+// These six functions are not used, and are in fact obsoleted by the other
+// functionality implemented in this file. The standard MIG-generated exc_server
+// (in excServer.c) and mach_exc_server (in mach_excServer.c) server dispatch
+// routines usable with the standard mach_msg_server() function call out to
+// these functions. exc_server() and mach_exc_server() are unused and are
+// replaced by the more flexible ExcServer and MachExcServer, but the linker
+// still needs to see these six function definitions.
+
+kern_return_t catch_exception_raise(exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count) {
+ NOTREACHED();
+ return KERN_FAILURE;
+}
+
+kern_return_t catch_exception_raise_state(
+ exception_handler_t exception_port,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count) {
+ NOTREACHED();
+ return KERN_FAILURE;
+}
+
+kern_return_t catch_exception_raise_state_identity(
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ exception_data_t code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count) {
+ NOTREACHED();
+ return KERN_FAILURE;
+}
+
+kern_return_t catch_mach_exception_raise(exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count) {
+ NOTREACHED();
+ return KERN_FAILURE;
+}
+
+kern_return_t catch_mach_exception_raise_state(
+ exception_handler_t exception_port,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count) {
+ NOTREACHED();
+ return KERN_FAILURE;
+}
+
+kern_return_t catch_mach_exception_raise_state_identity(
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ mach_exception_data_t code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ thread_state_t old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count) {
+ NOTREACHED();
+ return KERN_FAILURE;
+}
+
+} // extern "C"
+
+namespace crashpad {
+
+namespace {
+
+// Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with
+// the exc subsystem.
+struct ExcTraits {
+ using ExceptionCode = exception_data_type_t;
+
+ using RequestUnion = __RequestUnion__exc_subsystem;
+ using ReplyUnion = __ReplyUnion__exc_subsystem;
+
+ using ExceptionRaiseRequest = __Request__exception_raise_t;
+ using ExceptionRaiseStateRequest = __Request__exception_raise_state_t;
+ using ExceptionRaiseStateIdentityRequest =
+ __Request__exception_raise_state_identity_t;
+
+ using ExceptionRaiseReply = __Reply__exception_raise_t;
+ using ExceptionRaiseStateReply = __Reply__exception_raise_state_t;
+ using ExceptionRaiseStateIdentityReply =
+ __Reply__exception_raise_state_identity_t;
+
+ // The MIG-generated __MIG_check__Request__*() functions are not declared as
+ // accepting const data, but they could have been because they in fact do not
+ // modify the data.
+
+ static kern_return_t MIGCheckRequestExceptionRaise(
+ const ExceptionRaiseRequest* in_request) {
+ return __MIG_check__Request__exception_raise_t(
+ const_cast<ExceptionRaiseRequest*>(in_request));
+ }
+
+ static kern_return_t MIGCheckRequestExceptionRaiseState(
+ const ExceptionRaiseStateRequest* in_request,
+ const ExceptionRaiseStateRequest** in_request_1) {
+ return __MIG_check__Request__exception_raise_state_t(
+ const_cast<ExceptionRaiseStateRequest*>(in_request),
+ const_cast<ExceptionRaiseStateRequest**>(in_request_1));
+ }
+
+ static kern_return_t MIGCheckRequestExceptionRaiseStateIdentity(
+ const ExceptionRaiseStateIdentityRequest* in_request,
+ const ExceptionRaiseStateIdentityRequest** in_request_1) {
+ return __MIG_check__Request__exception_raise_state_identity_t(
+ const_cast<ExceptionRaiseStateIdentityRequest*>(in_request),
+ const_cast<ExceptionRaiseStateIdentityRequest**>(in_request_1));
+ }
+
+ // There are no predefined constants for these.
+ static const mach_msg_id_t kMachMessageIDExceptionRaise = 2401;
+ static const mach_msg_id_t kMachMessageIDExceptionRaiseState = 2402;
+ static const mach_msg_id_t kMachMessageIDExceptionRaiseStateIdentity = 2403;
+
+ static const exception_behavior_t kExceptionBehavior = 0;
+};
+
+// Traits for ExcServer<> and SimplifiedExcServer<> adapting them for use with
+// the mach_exc subsystem.
+struct MachExcTraits {
+ using ExceptionCode = mach_exception_data_type_t;
+
+ using RequestUnion = __RequestUnion__mach_exc_subsystem;
+ using ReplyUnion = __ReplyUnion__mach_exc_subsystem;
+
+ using ExceptionRaiseRequest = __Request__mach_exception_raise_t;
+ using ExceptionRaiseStateRequest = __Request__mach_exception_raise_state_t;
+ using ExceptionRaiseStateIdentityRequest =
+ __Request__mach_exception_raise_state_identity_t;
+
+ using ExceptionRaiseReply = __Reply__mach_exception_raise_t;
+ using ExceptionRaiseStateReply = __Reply__mach_exception_raise_state_t;
+ using ExceptionRaiseStateIdentityReply =
+ __Reply__mach_exception_raise_state_identity_t;
+
+ // The MIG-generated __MIG_check__Request__*() functions are not declared as
+ // accepting const data, but they could have been because they in fact do not
+ // modify the data.
+
+ static kern_return_t MIGCheckRequestExceptionRaise(
+ const ExceptionRaiseRequest* in_request) {
+ return __MIG_check__Request__mach_exception_raise_t(
+ const_cast<ExceptionRaiseRequest*>(in_request));
+ }
+
+ static kern_return_t MIGCheckRequestExceptionRaiseState(
+ const ExceptionRaiseStateRequest* in_request,
+ const ExceptionRaiseStateRequest** in_request_1) {
+ return __MIG_check__Request__mach_exception_raise_state_t(
+ const_cast<ExceptionRaiseStateRequest*>(in_request),
+ const_cast<ExceptionRaiseStateRequest**>(in_request_1));
+ }
+
+ static kern_return_t MIGCheckRequestExceptionRaiseStateIdentity(
+ const ExceptionRaiseStateIdentityRequest* in_request,
+ const ExceptionRaiseStateIdentityRequest** in_request_1) {
+ return __MIG_check__Request__mach_exception_raise_state_identity_t(
+ const_cast<ExceptionRaiseStateIdentityRequest*>(in_request),
+ const_cast<ExceptionRaiseStateIdentityRequest**>(in_request_1));
+ }
+
+ // There are no predefined constants for these.
+ static const mach_msg_id_t kMachMessageIDExceptionRaise = 2405;
+ static const mach_msg_id_t kMachMessageIDExceptionRaiseState = 2406;
+ static const mach_msg_id_t kMachMessageIDExceptionRaiseStateIdentity = 2407;
+
+ static const exception_behavior_t kExceptionBehavior = MACH_EXCEPTION_CODES;
+};
+
+//! \brief A server interface for the `exc` or `mach_exc` Mach subsystems.
+template <typename Traits>
+class ExcServer : public MachMessageServer::Interface {
+ public:
+ //! \brief An interface that the different request messages that are a part of
+ //! the `exc` or `mach_exc` Mach subsystems can be dispatched to.
+ class Interface {
+ public:
+ //! \brief Handles exceptions raised by `exception_raise()` or
+ //! `mach_exception_raise()`.
+ //!
+ //! This behaves equivalently to a `catch_exception_raise()` function used
+ //! with `exc_server()`, or a `catch_mach_exception_raise()` function used
+ //! with `mach_exc_server()`.
+ //!
+ //! \param[in] trailer The trailer received with the request message.
+ //! \param[out] destroy_request `true` if the request message is to be
+ //! destroyed even when this method returns success. See
+ //! MachMessageServer::Interface.
+ virtual kern_return_t CatchExceptionRaise(
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_request) = 0;
+
+ //! \brief Handles exceptions raised by `exception_raise_state()` or
+ //! `mach_exception_raise_state()`.
+ //!
+ //! This behaves equivalently to a `catch_exception_raise_state()` function
+ //! used with `exc_server()`, or a `catch_mach_exception_raise_state()`
+ //! function used with `mach_exc_server()`.
+ //!
+ //! There is no \a destroy_request parameter because, unlike
+ //! CatchExceptionRaise() and CatchExceptionRaiseStateIdentity(), the
+ //! request message is not complex (it does not carry the \a thread or \a
+ //! task port rights) and thus there is nothing to destroy.
+ //!
+ //! \param[in] trailer The trailer received with the request message.
+ virtual kern_return_t CatchExceptionRaiseState(
+ exception_handler_t exception_port,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer) = 0;
+
+ //! \brief Handles exceptions raised by `exception_raise_state_identity()`
+ //! or `mach_exception_raise_state_identity()`.
+ //!
+ //! This behaves equivalently to a `catch_exception_raise_state_identity()`
+ //! function used with `exc_server()`, or a
+ //! `catch_mach_exception_raise_state_identity()` function used with
+ //! `mach_exc_server()`.
+ //!
+ //! \param[in] trailer The trailer received with the request message.
+ //! \param[out] destroy_request `true` if the request message is to be
+ //! destroyed even when this method returns success. See
+ //! MachMessageServer::Interface.
+ virtual kern_return_t CatchExceptionRaiseStateIdentity(
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_request) = 0;
+
+ protected:
+ ~Interface() {}
+ };
+
+ //! \brief Constructs an object of this class.
+ //!
+ //! \param[in] interface The interface to dispatch requests to. Weak.
+ explicit ExcServer(Interface* interface)
+ : MachMessageServer::Interface(), interface_(interface) {}
+
+ // 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 Traits::kMachMessageIDExceptionRaise: {
+ // exception_raise(), catch_exception_raise(), mach_exception_raise(),
+ // catch_mach_exception_raise().
+ using Request = typename Traits::ExceptionRaiseRequest;
+ const Request* in_request = reinterpret_cast<const Request*>(in_header);
+ kern_return_t kr = Traits::MIGCheckRequestExceptionRaise(in_request);
+ if (kr != MACH_MSG_SUCCESS) {
+ SetMIGReplyError(out_header, kr);
+ return true;
+ }
+
+ using Reply = typename Traits::ExceptionRaiseReply;
+ Reply* out_reply = reinterpret_cast<Reply*>(out_header);
+ out_reply->RetCode =
+ interface_->CatchExceptionRaise(in_header->msgh_local_port,
+ in_request->thread.name,
+ in_request->task.name,
+ in_request->exception,
+ in_request->code,
+ in_request->codeCnt,
+ in_trailer,
+ destroy_complex_request);
+ if (out_reply->RetCode != KERN_SUCCESS) {
+ return true;
+ }
+
+ out_header->msgh_size = sizeof(*out_reply);
+ return true;
+ }
+
+ case Traits::kMachMessageIDExceptionRaiseState: {
+ // exception_raise_state(), catch_exception_raise_state(),
+ // mach_exception_raise_state(), catch_mach_exception_raise_state().
+ using Request = typename Traits::ExceptionRaiseStateRequest;
+ const Request* in_request = reinterpret_cast<const Request*>(in_header);
+
+ // in_request_1 is used for the portion of the request after the codes,
+ // which in theory can be variable-length. The check function will set it.
+ const Request* in_request_1;
+ kern_return_t kr =
+ Traits::MIGCheckRequestExceptionRaiseState(in_request, &in_request_1);
+ if (kr != MACH_MSG_SUCCESS) {
+ SetMIGReplyError(out_header, kr);
+ return true;
+ }
+
+ using Reply = typename Traits::ExceptionRaiseStateReply;
+ Reply* out_reply = reinterpret_cast<Reply*>(out_header);
+ out_reply->flavor = in_request_1->flavor;
+ out_reply->new_stateCnt = arraysize(out_reply->new_state);
+ out_reply->RetCode =
+ interface_->CatchExceptionRaiseState(in_header->msgh_local_port,
+ in_request->exception,
+ in_request->code,
+ in_request->codeCnt,
+ &out_reply->flavor,
+ in_request_1->old_state,
+ in_request_1->old_stateCnt,
+ out_reply->new_state,
+ &out_reply->new_stateCnt,
+ in_trailer);
+ if (out_reply->RetCode != KERN_SUCCESS) {
+ return true;
+ }
+
+ out_header->msgh_size =
+ sizeof(*out_reply) - sizeof(out_reply->new_state) +
+ sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
+ return true;
+ }
+
+ case Traits::kMachMessageIDExceptionRaiseStateIdentity: {
+ // exception_raise_state_identity(),
+ // catch_exception_raise_state_identity(),
+ // mach_exception_raise_state_identity(),
+ // catch_mach_exception_raise_state_identity().
+ using Request = typename Traits::ExceptionRaiseStateIdentityRequest;
+ const Request* in_request = reinterpret_cast<const Request*>(in_header);
+
+ // in_request_1 is used for the portion of the request after the codes,
+ // which in theory can be variable-length. The check function will set it.
+ const Request* in_request_1;
+ kern_return_t kr = Traits::MIGCheckRequestExceptionRaiseStateIdentity(
+ in_request, &in_request_1);
+ if (kr != MACH_MSG_SUCCESS) {
+ SetMIGReplyError(out_header, kr);
+ return true;
+ }
+
+ using Reply = typename Traits::ExceptionRaiseStateIdentityReply;
+ Reply* out_reply = reinterpret_cast<Reply*>(out_header);
+ out_reply->flavor = in_request_1->flavor;
+ out_reply->new_stateCnt = arraysize(out_reply->new_state);
+ out_reply->RetCode = interface_->CatchExceptionRaiseStateIdentity(
+ in_header->msgh_local_port,
+ in_request->thread.name,
+ in_request->task.name,
+ in_request->exception,
+ in_request->code,
+ in_request->codeCnt,
+ &out_reply->flavor,
+ in_request_1->old_state,
+ in_request_1->old_stateCnt,
+ out_reply->new_state,
+ &out_reply->new_stateCnt,
+ in_trailer,
+ destroy_complex_request);
+ if (out_reply->RetCode != KERN_SUCCESS) {
+ return true;
+ }
+
+ out_header->msgh_size =
+ sizeof(*out_reply) - sizeof(out_reply->new_state) +
+ sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt;
+ return true;
+ }
+
+ default: {
+ SetMIGReplyError(out_header, MIG_BAD_ID);
+ return false;
+ }
+ }
+}
+
+//! \brief A server interface for the `exc` or `mach_exc` Mach subsystems,
+//! simplified to have only a single interface method needing
+//! implementation.
+template <typename Traits>
+class SimplifiedExcServer final : public ExcServer<Traits>,
+ public ExcServer<Traits>::Interface {
+ public:
+ //! \brief An interface that the different request messages that are a part of
+ //! the `exc` or `mach_exc` Mach subsystems can be dispatched to.
+ class Interface {
+ public:
+ //! \brief Handles exceptions raised by `exception_raise()`,
+ //! `exception_raise_state()`, and `exception_raise_state_identity()`;
+ //! or `mach_exception_raise()`, `mach_exception_raise_state()`, and
+ //! `mach_exception_raise_state_identity()`.
+ //!
+ //! For convenience in implementation, these different “behaviors” of
+ //! exception messages are all mapped to a single interface method. The
+ //! exception’s original “behavior” is specified in the \a behavior
+ //! parameter. Only parameters that were supplied in the request message
+ //! are populated, other parameters are set to reasonable default values.
+ //!
+ //! The meanings of most parameters are identical to that of
+ //! ExcServer<>::Interface::CatchExceptionRaiseStateIdentity().
+ //!
+ //! \param[in] behavior `EXCEPTION_DEFAULT`, `EXCEPTION_STATE`, or
+ //! `EXCEPTION_STATE_IDENTITY`, identifying which exception request
+ //! message was processed and thus which other parameters are valid.
+ //! When used with the `mach_exc` subsystem, `MACH_EXCEPTION_CODES` will
+ //! be ORed in to this parameter.
+ virtual kern_return_t CatchException(
+ exception_behavior_t behavior,
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_complex_request) = 0;
+
+ protected:
+ ~Interface() {}
+ };
+
+ //! \brief Constructs an object of this class.
+ //!
+ //! \param[in] interface The interface to dispatch requests to. Weak.
+ explicit SimplifiedExcServer(Interface* interface)
+ : ExcServer<Traits>(this),
+ ExcServer<Traits>::Interface(),
+ interface_(interface) {}
+
+ // ExcServer::Interface:
+
+ kern_return_t CatchExceptionRaise(exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_request) override {
+ thread_state_flavor_t flavor = THREAD_STATE_NONE;
+ mach_msg_type_number_t new_state_count = 0;
+ return interface_->CatchException(
+ Traits::kExceptionBehavior | EXCEPTION_DEFAULT,
+ exception_port,
+ thread,
+ task,
+ exception,
+ code_count ? code : nullptr,
+ code_count,
+ &flavor,
+ nullptr,
+ 0,
+ nullptr,
+ &new_state_count,
+ trailer,
+ destroy_request);
+ }
+
+ kern_return_t CatchExceptionRaiseState(
+ exception_handler_t exception_port,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer) override {
+ bool destroy_complex_request = false;
+ return interface_->CatchException(
+ Traits::kExceptionBehavior | EXCEPTION_STATE,
+ exception_port,
+ THREAD_NULL,
+ TASK_NULL,
+ exception,
+ code_count ? code : nullptr,
+ code_count,
+ flavor,
+ old_state_count ? old_state : nullptr,
+ old_state_count,
+ new_state_count ? new_state : nullptr,
+ new_state_count,
+ trailer,
+ &destroy_complex_request);
+ }
+
+ kern_return_t CatchExceptionRaiseStateIdentity(
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const typename Traits::ExceptionCode* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_request) override {
+ return interface_->CatchException(
+ Traits::kExceptionBehavior | EXCEPTION_STATE_IDENTITY,
+ exception_port,
+ thread,
+ task,
+ exception,
+ code_count ? code : nullptr,
+ code_count,
+ flavor,
+ old_state_count ? old_state : nullptr,
+ old_state_count,
+ new_state_count ? new_state : nullptr,
+ new_state_count,
+ trailer,
+ destroy_request);
+ }
+
+ private:
+ Interface* interface_; // weak
+
+ DISALLOW_COPY_AND_ASSIGN(SimplifiedExcServer);
+};
+
+} // namespace
+
+namespace internal {
+
+class UniversalMachExcServerImpl final
+ : public CompositeMachMessageServer,
+ public SimplifiedExcServer<ExcTraits>::Interface,
+ public SimplifiedExcServer<MachExcTraits>::Interface {
+ public:
+ explicit UniversalMachExcServerImpl(
+ UniversalMachExcServer::Interface* interface)
+ : CompositeMachMessageServer(),
+ SimplifiedExcServer<ExcTraits>::Interface(),
+ SimplifiedExcServer<MachExcTraits>::Interface(),
+ exc_server_(this),
+ mach_exc_server_(this),
+ interface_(interface) {
+ AddHandler(&exc_server_);
+ AddHandler(&mach_exc_server_);
+ }
+
+ ~UniversalMachExcServerImpl() {}
+
+ // SimplifiedExcServer<ExcTraits>::Interface:
+ kern_return_t CatchException(exception_behavior_t behavior,
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const exception_data_type_t* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_complex_request) {
+ std::vector<mach_exception_data_type_t> mach_codes;
+ mach_codes.reserve(code_count);
+ for (size_t index = 0; index < code_count; ++index) {
+ mach_codes.push_back(code[index]);
+ }
+
+ return interface_->CatchMachException(behavior,
+ exception_port,
+ thread,
+ task,
+ exception,
+ code_count ? &mach_codes[0] : nullptr,
+ code_count,
+ flavor,
+ old_state_count ? old_state : nullptr,
+ old_state_count,
+ new_state_count ? new_state : nullptr,
+ new_state_count,
+ trailer,
+ destroy_complex_request);
+ }
+
+ // SimplifiedExcServer<MachExcTraits>::Interface:
+ kern_return_t CatchException(exception_behavior_t behavior,
+ exception_handler_t exception_port,
+ thread_t thread,
+ task_t task,
+ exception_type_t exception,
+ const mach_exception_data_type_t* code,
+ mach_msg_type_number_t code_count,
+ thread_state_flavor_t* flavor,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count,
+ const mach_msg_trailer_t* trailer,
+ bool* destroy_complex_request) {
+ return interface_->CatchMachException(behavior,
+ exception_port,
+ thread,
+ task,
+ exception,
+ code_count ? code : nullptr,
+ code_count,
+ flavor,
+ old_state_count ? old_state : nullptr,
+ old_state_count,
+ new_state_count ? new_state : nullptr,
+ new_state_count,
+ trailer,
+ destroy_complex_request);
+ }
+
+ private:
+ SimplifiedExcServer<ExcTraits> exc_server_;
+ SimplifiedExcServer<MachExcTraits> mach_exc_server_;
+ UniversalMachExcServer::Interface* interface_; // weak
+
+ DISALLOW_COPY_AND_ASSIGN(UniversalMachExcServerImpl);
+};
+
+} // namespace internal
+
+UniversalMachExcServer::UniversalMachExcServer(
+ UniversalMachExcServer::Interface* interface)
+ : MachMessageServer::Interface(),
+ impl_(new internal::UniversalMachExcServerImpl(interface)) {
+}
+
+UniversalMachExcServer::~UniversalMachExcServer() {
+}
+
+bool UniversalMachExcServer::MachMessageServerFunction(
+ const mach_msg_header_t* in_header,
+ mach_msg_header_t* out_header,
+ bool* destroy_complex_request) {
+ return impl_->MachMessageServerFunction(
+ in_header, out_header, destroy_complex_request);
+}
+
+std::set<mach_msg_id_t> UniversalMachExcServer::MachMessageServerRequestIDs() {
+ return impl_->MachMessageServerRequestIDs();
+}
+
+mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() {
+ return impl_->MachMessageServerRequestSize();
+}
+
+mach_msg_size_t UniversalMachExcServer::MachMessageServerReplySize() {
+ return impl_->MachMessageServerReplySize();
+}
+
+kern_return_t ExcServerSuccessfulReturnValue(exception_type_t exception,
+ exception_behavior_t behavior,
+ bool set_thread_state) {
+ if (exception == EXC_CRASH
+#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11
+ && MacOSXMinorVersion() >= 11
+#endif
+ ) {
+ return KERN_SUCCESS;
+ }
+
+ if (!set_thread_state && ExceptionBehaviorHasState(behavior)) {
+ return MACH_RCV_PORT_DIED;
+ }
+
+ return KERN_SUCCESS;
+}
+
+void ExcServerCopyState(exception_behavior_t behavior,
+ ConstThreadState old_state,
+ mach_msg_type_number_t old_state_count,
+ thread_state_t new_state,
+ mach_msg_type_number_t* new_state_count) {
+ if (ExceptionBehaviorHasState(behavior)) {
+ *new_state_count = std::min(old_state_count, *new_state_count);
+ memcpy(new_state, old_state, *new_state_count * sizeof(old_state[0]));
+ }
+}
+
+} // namespace crashpad

Powered by Google App Engine
This is Rietveld 408576698