Index: util/mach/exc_client_variants.cc |
diff --git a/util/mach/exc_client_variants.cc b/util/mach/exc_client_variants.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..46a9f50c71252ef3c260b077c2e163c197a7c8cd |
--- /dev/null |
+++ b/util/mach/exc_client_variants.cc |
@@ -0,0 +1,130 @@ |
+// 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_client_variants.h" |
+ |
+#include <vector> |
+ |
+#include "base/logging.h" |
+#include "util/mach/exc.h" |
+#include "util/mach/mach_exc.h" |
+#include "util/mach/mach_extensions.h" |
+ |
+namespace crashpad { |
+ |
+kern_return_t UniversalExceptionRaise(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) { |
+ // This function is similar to 10.9.4 xnu-2422.110.17/osfmk/kern/exception.c |
+ // exception_deliver() as far as the delivery logic is concerned. Unlike |
+ // exception_deliver(), this function does not get or set thread states for |
+ // behavior values that require this, as that is left to the caller to do if |
+ // needed. |
+ |
+ std::vector<exception_data_type_t> small_code_vector; |
+ exception_data_t small_code = NULL; |
+ if ((behavior & MACH_EXCEPTION_CODES) == 0 && code_count) { |
+ small_code_vector.reserve(code_count); |
+ for (size_t code_index = 0; code_index < code_count; ++code_index) { |
+ small_code_vector[code_index] = code[code_index]; |
+ } |
+ small_code = &small_code_vector[0]; |
+ } |
+ |
+ // The *exception_raise*() family has bad declarations. Their code and |
+ // old_state arguments aren’t pointers to const data, although they should be. |
+ // The generated stubs in excUser.c and mach_excUser.c make it clear that the |
+ // data is never modified, and these parameters could be declared with const |
+ // appropriately. The uses of const_cast below are thus safe. |
+ |
+ switch (behavior) { |
+ case EXCEPTION_DEFAULT: |
+ return exception_raise( |
+ exception_port, thread, task, exception, small_code, code_count); |
+ |
+ case EXCEPTION_STATE: |
+ return exception_raise_state(exception_port, |
+ exception, |
+ small_code, |
+ code_count, |
+ flavor, |
+ const_cast<thread_state_t>(old_state), |
+ old_state_count, |
+ new_state, |
+ new_state_count); |
+ |
+ case EXCEPTION_STATE_IDENTITY: |
+ return exception_raise_state_identity( |
+ exception_port, |
+ thread, |
+ task, |
+ exception, |
+ small_code, |
+ code_count, |
+ flavor, |
+ const_cast<thread_state_t>(old_state), |
+ old_state_count, |
+ new_state, |
+ new_state_count); |
+ |
+ case EXCEPTION_DEFAULT | kMachExceptionCodes: |
+ return mach_exception_raise(exception_port, |
+ thread, |
+ task, |
+ exception, |
+ const_cast<mach_exception_data_type_t*>(code), |
+ code_count); |
+ |
+ case EXCEPTION_STATE | kMachExceptionCodes: |
+ return mach_exception_raise_state( |
+ exception_port, |
+ exception, |
+ const_cast<mach_exception_data_type_t*>(code), |
+ code_count, |
+ flavor, |
+ const_cast<thread_state_t>(old_state), |
+ old_state_count, |
+ new_state, |
+ new_state_count); |
+ |
+ case EXCEPTION_STATE_IDENTITY | kMachExceptionCodes: |
+ return mach_exception_raise_state_identity( |
+ exception_port, |
+ thread, |
+ task, |
+ exception, |
+ const_cast<mach_exception_data_type_t*>(code), |
+ code_count, |
+ flavor, |
+ const_cast<thread_state_t>(old_state), |
+ old_state_count, |
+ new_state, |
+ new_state_count); |
+ |
+ default: |
+ NOTREACHED(); |
+ return KERN_INVALID_ARGUMENT; |
+ } |
+} |
+ |
+} // namespace crashpad |