| Index: util/mach/exc_server_variants.cc | 
| diff --git a/util/mach/exc_server_variants.cc b/util/mach/exc_server_variants.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..5ecd05d5f2a94d48cff5ef75669ad78abba9ee34 | 
| --- /dev/null | 
| +++ b/util/mach/exc_server_variants.cc | 
| @@ -0,0 +1,674 @@ | 
| +// 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 <algorithm> | 
| +#include <vector> | 
| + | 
| +#include "base/basictypes.h" | 
| +#include "base/logging.h" | 
| +#include "util/mach/exc.h" | 
| +#include "util/mach/excServer.h" | 
| +#include "util/mach/mach_exc.h" | 
| +#include "util/mach/mach_excServer.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 { | 
| + | 
| +void PrepareReplyFromRequest(const mach_msg_header_t* in_header, | 
| +                             mach_msg_header_t* out_header) { | 
| +  out_header->msgh_bits = | 
| +      MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(in_header->msgh_bits), 0); | 
| +  out_header->msgh_remote_port = in_header->msgh_remote_port; | 
| +  out_header->msgh_size = sizeof(mig_reply_error_t); | 
| +  out_header->msgh_local_port = MACH_PORT_NULL; | 
| +  out_header->msgh_id = in_header->msgh_id + 100; | 
| +  reinterpret_cast<mig_reply_error_t*>(out_header)->NDR = NDR_record; | 
| +} | 
| + | 
| +void SetReplyError(mach_msg_header_t* out_header, kern_return_t error) { | 
| +  reinterpret_cast<mig_reply_error_t*>(out_header)->RetCode = error; | 
| +} | 
| + | 
| +// 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, | 
| +}; | 
| + | 
| +}  // namespace | 
| + | 
| +namespace crashpad { | 
| +namespace internal { | 
| + | 
| +ExcServer::ExcServer(ExcServer::Interface* interface) | 
| +    : MachMessageServer::Interface(), | 
| +      interface_(interface) { | 
| +} | 
| + | 
| +bool ExcServer::MachMessageServerFunction(mach_msg_header_t* in_header, | 
| +                                          mach_msg_header_t* out_header, | 
| +                                          bool* destroy_complex_request) { | 
| +  PrepareReplyFromRequest(in_header, out_header); | 
| + | 
| +  switch (in_header->msgh_id) { | 
| +    case kMachMessageIDExceptionRaise: { | 
| +      // exception_raise(), catch_exception_raise(). | 
| +      typedef __Request__exception_raise_t Request; | 
| +      Request* in_request = reinterpret_cast<Request*>(in_header); | 
| +      kern_return_t kr = __MIG_check__Request__exception_raise_t(in_request); | 
| +      if (kr != MACH_MSG_SUCCESS) { | 
| +        SetReplyError(out_header, kr); | 
| +        return true; | 
| +      } | 
| + | 
| +      typedef __Reply__exception_raise_t Reply; | 
| +      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, | 
| +                                          destroy_complex_request); | 
| +      if (out_reply->RetCode != KERN_SUCCESS) { | 
| +        return true; | 
| +      } | 
| + | 
| +      out_header->msgh_size = sizeof(*out_reply); | 
| +      return true; | 
| +    } | 
| + | 
| +    case kMachMessageIDExceptionRaiseState: { | 
| +      // exception_raise_state(), catch_exception_raise_state(). | 
| +      typedef __Request__exception_raise_state_t Request; | 
| +      Request* in_request = reinterpret_cast<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. | 
| +      Request* in_request_1; | 
| +      kern_return_t kr = __MIG_check__Request__exception_raise_state_t( | 
| +          in_request, &in_request_1); | 
| +      if (kr != MACH_MSG_SUCCESS) { | 
| +        SetReplyError(out_header, kr); | 
| +        return true; | 
| +      } | 
| + | 
| +      typedef __Reply__exception_raise_state_t Reply; | 
| +      Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 
| +      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, | 
| +                                               &in_request_1->flavor, | 
| +                                               in_request_1->old_state, | 
| +                                               in_request_1->old_stateCnt, | 
| +                                               out_reply->new_state, | 
| +                                               &out_reply->new_stateCnt); | 
| +      if (out_reply->RetCode != KERN_SUCCESS) { | 
| +        return true; | 
| +      } | 
| + | 
| +      out_reply->flavor = in_request_1->flavor; | 
| +      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 kMachMessageIDExceptionRaiseStateIdentity: { | 
| +      // exception_raise_state_identity(), | 
| +      // catch_exception_raise_state_identity(). | 
| +      typedef __Request__exception_raise_state_identity_t Request; | 
| +      Request* in_request = reinterpret_cast<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. | 
| +      Request* in_request_1; | 
| +      kern_return_t kr = __MIG_check__Request__exception_raise_state_identity_t( | 
| +          in_request, &in_request_1); | 
| +      if (kr != MACH_MSG_SUCCESS) { | 
| +        SetReplyError(out_header, kr); | 
| +        return true; | 
| +      } | 
| + | 
| +      typedef __Reply__exception_raise_state_identity_t Reply; | 
| +      Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 
| +      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, | 
| +          &in_request_1->flavor, | 
| +          in_request_1->old_state, | 
| +          in_request_1->old_stateCnt, | 
| +          out_reply->new_state, | 
| +          &out_reply->new_stateCnt, | 
| +          destroy_complex_request); | 
| +      if (out_reply->RetCode != KERN_SUCCESS) { | 
| +        return true; | 
| +      } | 
| + | 
| +      out_reply->flavor = in_request_1->flavor; | 
| +      out_header->msgh_size = | 
| +          sizeof(*out_reply) - sizeof(out_reply->new_state) + | 
| +          sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; | 
| +      return true; | 
| +    } | 
| +  } | 
| + | 
| +  SetReplyError(out_header, MIG_BAD_ID); | 
| +  return false; | 
| +} | 
| + | 
| +mach_msg_size_t ExcServer::MachMessageServerRequestSize() { | 
| +  return sizeof(__RequestUnion__exc_subsystem); | 
| +} | 
| + | 
| +mach_msg_size_t ExcServer::MachMessageServerReplySize() { | 
| +  return sizeof(__ReplyUnion__exc_subsystem); | 
| +} | 
| + | 
| +MachExcServer::MachExcServer(MachExcServer::Interface* interface) | 
| +    : MachMessageServer::Interface(), | 
| +      interface_(interface) { | 
| +} | 
| + | 
| +bool MachExcServer::MachMessageServerFunction(mach_msg_header_t* in_header, | 
| +                                              mach_msg_header_t* out_header, | 
| +                                              bool* destroy_complex_request) { | 
| +  PrepareReplyFromRequest(in_header, out_header); | 
| + | 
| +  switch (in_header->msgh_id) { | 
| +    case kMachMessageIDMachExceptionRaise: { | 
| +      // mach_exception_raise(), catch_mach_exception_raise(). | 
| +      typedef __Request__mach_exception_raise_t Request; | 
| +      Request* in_request = reinterpret_cast<Request*>(in_header); | 
| +      kern_return_t kr = | 
| +          __MIG_check__Request__mach_exception_raise_t(in_request); | 
| +      if (kr != MACH_MSG_SUCCESS) { | 
| +        SetReplyError(out_header, kr); | 
| +        return true; | 
| +      } | 
| + | 
| +      typedef __Reply__mach_exception_raise_t Reply; | 
| +      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, | 
| +                                              destroy_complex_request); | 
| +      if (out_reply->RetCode != KERN_SUCCESS) { | 
| +        return true; | 
| +      } | 
| + | 
| +      out_header->msgh_size = sizeof(*out_reply); | 
| +      return true; | 
| +    } | 
| + | 
| +    case kMachMessageIDMachExceptionRaiseState: { | 
| +      // mach_exception_raise_state(), catch_mach_exception_raise_state(). | 
| +      typedef __Request__mach_exception_raise_state_t Request; | 
| +      Request* in_request = reinterpret_cast<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. | 
| +      Request* in_request_1; | 
| +      kern_return_t kr = __MIG_check__Request__mach_exception_raise_state_t( | 
| +          in_request, &in_request_1); | 
| +      if (kr != MACH_MSG_SUCCESS) { | 
| +        SetReplyError(out_header, kr); | 
| +        return true; | 
| +      } | 
| + | 
| +      typedef __Reply__mach_exception_raise_state_t Reply; | 
| +      Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 
| +      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, | 
| +                                                   &in_request_1->flavor, | 
| +                                                   in_request_1->old_state, | 
| +                                                   in_request_1->old_stateCnt, | 
| +                                                   out_reply->new_state, | 
| +                                                   &out_reply->new_stateCnt); | 
| +      if (out_reply->RetCode != KERN_SUCCESS) { | 
| +        return true; | 
| +      } | 
| + | 
| +      out_reply->flavor = in_request_1->flavor; | 
| +      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 kMachMessageIDMachExceptionRaiseStateIdentity: { | 
| +      // mach_exception_raise_state_identity(), | 
| +      // catch_mach_exception_raise_state_identity(). | 
| +      typedef __Request__mach_exception_raise_state_identity_t Request; | 
| +      Request* in_request = reinterpret_cast<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. | 
| +      Request* in_request_1; | 
| +      kern_return_t kr = | 
| +          __MIG_check__Request__mach_exception_raise_state_identity_t( | 
| +              in_request, &in_request_1); | 
| +      if (kr != MACH_MSG_SUCCESS) { | 
| +        SetReplyError(out_header, kr); | 
| +        return true; | 
| +      } | 
| + | 
| +      typedef __Reply__mach_exception_raise_state_identity_t Reply; | 
| +      Reply* out_reply = reinterpret_cast<Reply*>(out_header); | 
| +      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, | 
| +          &in_request_1->flavor, | 
| +          in_request_1->old_state, | 
| +          in_request_1->old_stateCnt, | 
| +          out_reply->new_state, | 
| +          &out_reply->new_stateCnt, | 
| +          destroy_complex_request); | 
| +      if (out_reply->RetCode != KERN_SUCCESS) { | 
| +        return true; | 
| +      } | 
| + | 
| +      out_reply->flavor = in_request_1->flavor; | 
| +      out_header->msgh_size = | 
| +          sizeof(*out_reply) - sizeof(out_reply->new_state) + | 
| +          sizeof(out_reply->new_state[0]) * out_reply->new_stateCnt; | 
| +      return true; | 
| +    } | 
| +  } | 
| + | 
| +  SetReplyError(out_header, MIG_BAD_ID); | 
| +  return false; | 
| +} | 
| + | 
| +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, | 
| +    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, | 
| +                                    code_count, | 
| +                                    &flavor, | 
| +                                    NULL, | 
| +                                    0, | 
| +                                    NULL, | 
| +                                    &new_state_count, | 
| +                                    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) { | 
| +  bool destroy_complex_request = false; | 
| +  return interface_->CatchException(EXCEPTION_STATE, | 
| +                                    exception_port, | 
| +                                    MACH_PORT_NULL, | 
| +                                    MACH_PORT_NULL, | 
| +                                    exception, | 
| +                                    code, | 
| +                                    code_count, | 
| +                                    flavor, | 
| +                                    old_state, | 
| +                                    old_state_count, | 
| +                                    new_state, | 
| +                                    new_state_count, | 
| +                                    &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, | 
| +    bool* destroy_request) { | 
| +  return interface_->CatchException(EXCEPTION_STATE_IDENTITY, | 
| +                                    exception_port, | 
| +                                    thread, | 
| +                                    task, | 
| +                                    exception, | 
| +                                    code, | 
| +                                    code_count, | 
| +                                    flavor, | 
| +                                    old_state, | 
| +                                    old_state_count, | 
| +                                    new_state, | 
| +                                    new_state_count, | 
| +                                    destroy_request); | 
| +} | 
| + | 
| +SimplifiedMachExcServer::SimplifiedMachExcServer( | 
| +    SimplifiedMachExcServer::Interface* interface) | 
| +    : MachExcServer(this), | 
| +      MachExcServer::Interface(), | 
| +      interface_(interface) { | 
| +} | 
| + | 
| +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, | 
| +    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, | 
| +      code_count, | 
| +      &flavor, | 
| +      NULL, | 
| +      0, | 
| +      NULL, | 
| +      &new_state_count, | 
| +      destroy_request); | 
| +} | 
| + | 
| +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) { | 
| +  bool destroy_complex_request = false; | 
| +  return interface_->CatchMachException(EXCEPTION_STATE | MACH_EXCEPTION_CODES, | 
| +                                        exception_port, | 
| +                                        MACH_PORT_NULL, | 
| +                                        MACH_PORT_NULL, | 
| +                                        exception, | 
| +                                        code, | 
| +                                        code_count, | 
| +                                        flavor, | 
| +                                        old_state, | 
| +                                        old_state_count, | 
| +                                        new_state, | 
| +                                        new_state_count, | 
| +                                        &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, | 
| +    bool* destroy_request) { | 
| +  return interface_->CatchMachException( | 
| +      EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, | 
| +      exception_port, | 
| +      thread, | 
| +      task, | 
| +      exception, | 
| +      code, | 
| +      code_count, | 
| +      flavor, | 
| +      old_state, | 
| +      old_state_count, | 
| +      new_state, | 
| +      new_state_count, | 
| +      destroy_request); | 
| +} | 
| + | 
| +}  // namespace internal | 
| + | 
| +UniversalMachExcServer::UniversalMachExcServer() | 
| +    : MachMessageServer::Interface(), | 
| +      internal::SimplifiedExcServer::Interface(), | 
| +      internal::SimplifiedMachExcServer::Interface(), | 
| +      exc_server_(this), | 
| +      mach_exc_server_(this) { | 
| +} | 
| + | 
| +bool UniversalMachExcServer::MachMessageServerFunction( | 
| +    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. | 
| +  PrepareReplyFromRequest(in_header, out_header); | 
| +  SetReplyError(out_header, MIG_BAD_ID); | 
| +  return false; | 
| +} | 
| + | 
| +mach_msg_size_t UniversalMachExcServer::MachMessageServerRequestSize() { | 
| +  return std::max(mach_exc_server_.MachMessageServerRequestSize(), | 
| +                  exc_server_.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, | 
| +    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 CatchMachException(behavior, | 
| +                            exception_port, | 
| +                            thread, | 
| +                            task, | 
| +                            exception, | 
| +                            code_count ? &mach_codes[0] : NULL, | 
| +                            code_count, | 
| +                            flavor, | 
| +                            old_state, | 
| +                            old_state_count, | 
| +                            new_state, | 
| +                            new_state_count, | 
| +                            destroy_complex_request); | 
| +} | 
| + | 
| +}  // namespace crashpad | 
|  |