| OLD | NEW |
| 1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 //! handler. If `false`, this will be suppressed, even when \a behavior | 52 //! handler. If `false`, this will be suppressed, even when \a behavior |
| 53 //! indicates that the handler receives and returns a thread state. | 53 //! indicates that the handler receives and returns a thread state. |
| 54 //! | 54 //! |
| 55 //! \return `true` if the exception was delivered to the handler and the handler | 55 //! \return `true` if the exception was delivered to the handler and the handler |
| 56 //! indicated success. `false` otherwise, with a warning message logged. | 56 //! indicated success. `false` otherwise, with a warning message logged. |
| 57 bool DeliverException(thread_t thread, | 57 bool DeliverException(thread_t thread, |
| 58 task_t task, | 58 task_t task, |
| 59 exception_type_t exception, | 59 exception_type_t exception, |
| 60 const mach_exception_data_t code, | 60 const mach_exception_data_t code, |
| 61 mach_msg_type_number_t code_count, | 61 mach_msg_type_number_t code_count, |
| 62 const NativeCPUContext* cpu_context, | 62 const NativeCPUContext& cpu_context, |
| 63 const ExceptionPorts::ExceptionHandler& handler, | 63 const ExceptionPorts::ExceptionHandler& handler, |
| 64 bool set_state) { | 64 bool set_state) { |
| 65 kern_return_t kr; | 65 kern_return_t kr; |
| 66 | 66 |
| 67 bool handler_wants_state = ExceptionBehaviorHasState(handler.behavior); | 67 bool handler_wants_state = ExceptionBehaviorHasState(handler.behavior); |
| 68 if (!handler_wants_state) { | 68 if (!handler_wants_state) { |
| 69 // Regardless of the passed-in value of |set_state|, if the handler won’t be | 69 // Regardless of the passed-in value of |set_state|, if the handler won’t be |
| 70 // dealing with any state at all, no state should be set. | 70 // dealing with any state at all, no state should be set. |
| 71 set_state = false; | 71 set_state = false; |
| 72 } | 72 } |
| 73 | 73 |
| 74 // old_state is only used if the context already captured doesn’t match (or | 74 // old_state is only used if the context already captured doesn’t match (or |
| 75 // can’t be converted to) what’s registered for the handler. | 75 // can’t be converted to) what’s registered for the handler. |
| 76 thread_state_data_t old_state; | 76 thread_state_data_t old_state; |
| 77 | 77 |
| 78 thread_state_flavor_t flavor = handler.flavor; | 78 thread_state_flavor_t flavor = handler.flavor; |
| 79 ConstThreadState state; | 79 ConstThreadState state; |
| 80 mach_msg_type_number_t state_count; | 80 mach_msg_type_number_t state_count; |
| 81 switch (flavor) { | 81 switch (flavor) { |
| 82 #if defined(ARCH_CPU_X86_FAMILY) | 82 #if defined(ARCH_CPU_X86_FAMILY) |
| 83 case x86_THREAD_STATE: | 83 case x86_THREAD_STATE: |
| 84 state = reinterpret_cast<ConstThreadState>(cpu_context); | 84 state = reinterpret_cast<ConstThreadState>(&cpu_context); |
| 85 state_count = x86_THREAD_STATE_COUNT; | 85 state_count = x86_THREAD_STATE_COUNT; |
| 86 break; | 86 break; |
| 87 #if defined(ARCH_CPU_X86) | 87 #if defined(ARCH_CPU_X86) |
| 88 case x86_THREAD_STATE32: | 88 case x86_THREAD_STATE32: |
| 89 state = reinterpret_cast<ConstThreadState>(&cpu_context->uts.ts32); | 89 state = reinterpret_cast<ConstThreadState>(&cpu_context.uts.ts32); |
| 90 state_count = cpu_context->tsh.count; | 90 state_count = cpu_context.tsh.count; |
| 91 break; | 91 break; |
| 92 #elif defined(ARCH_CPU_X86_64) | 92 #elif defined(ARCH_CPU_X86_64) |
| 93 case x86_THREAD_STATE64: | 93 case x86_THREAD_STATE64: |
| 94 state = reinterpret_cast<ConstThreadState>(&cpu_context->uts.ts64); | 94 state = reinterpret_cast<ConstThreadState>(&cpu_context.uts.ts64); |
| 95 state_count = cpu_context->tsh.count; | 95 state_count = cpu_context.tsh.count; |
| 96 break; | 96 break; |
| 97 #endif | 97 #endif |
| 98 #else | 98 #else |
| 99 #error Port to your CPU architecture | 99 #error Port to your CPU architecture |
| 100 #endif | 100 #endif |
| 101 | 101 |
| 102 case THREAD_STATE_NONE: | 102 case THREAD_STATE_NONE: |
| 103 // This is only acceptable if the handler doesn’t have one of the “state” | 103 // This is only acceptable if the handler doesn’t have one of the “state” |
| 104 // behaviors. Otherwise, if the kernel were attempting to send an | 104 // behaviors. Otherwise, if the kernel were attempting to send an |
| 105 // exception message to this port, it would call thread_getstatus() (known | 105 // exception message to this port, it would call thread_getstatus() (known |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 169 if (kr == KERN_SUCCESS && set_state) { | 169 if (kr == KERN_SUCCESS && set_state) { |
| 170 kr = thread_set_state(thread, flavor, new_state, new_state_count); | 170 kr = thread_set_state(thread, flavor, new_state, new_state_count); |
| 171 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "thread_set_state"; | 171 MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "thread_set_state"; |
| 172 } | 172 } |
| 173 | 173 |
| 174 return success; | 174 return success; |
| 175 } | 175 } |
| 176 | 176 |
| 177 } // namespace | 177 } // namespace |
| 178 | 178 |
| 179 void SimulateCrash(const NativeCPUContext* cpu_context) { | 179 void SimulateCrash(const NativeCPUContext& cpu_context) { |
| 180 #if defined(ARCH_CPU_X86) | 180 #if defined(ARCH_CPU_X86) |
| 181 DCHECK_EQ(cpu_context->tsh.flavor, | 181 DCHECK_EQ(cpu_context.tsh.flavor, |
| 182 implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32)); | 182 implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32)); |
| 183 DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context->tsh.count), | 183 DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context.tsh.count), |
| 184 x86_THREAD_STATE32_COUNT); | 184 x86_THREAD_STATE32_COUNT); |
| 185 #elif defined(ARCH_CPU_X86_64) | 185 #elif defined(ARCH_CPU_X86_64) |
| 186 DCHECK_EQ(cpu_context->tsh.flavor, | 186 DCHECK_EQ(cpu_context.tsh.flavor, |
| 187 implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64)); | 187 implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64)); |
| 188 DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context->tsh.count), | 188 DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context.tsh.count), |
| 189 x86_THREAD_STATE64_COUNT); | 189 x86_THREAD_STATE64_COUNT); |
| 190 #endif | 190 #endif |
| 191 | 191 |
| 192 base::mac::ScopedMachSendRight thread(mach_thread_self()); | 192 base::mac::ScopedMachSendRight thread(mach_thread_self()); |
| 193 exception_type_t exception = kMachExceptionSimulated; | 193 exception_type_t exception = kMachExceptionSimulated; |
| 194 mach_exception_data_type_t codes[] = {0, 0}; | 194 mach_exception_data_type_t codes[] = {0, 0}; |
| 195 mach_msg_type_number_t code_count = arraysize(codes); | 195 mach_msg_type_number_t code_count = arraysize(codes); |
| 196 | 196 |
| 197 // Look up the handler for EXC_CRASH exceptions in the same way that the | 197 // Look up the handler for EXC_CRASH exceptions in the same way that the |
| 198 // kernel would: try a thread handler, then a task handler, and finally a host | 198 // kernel would: try a thread handler, then a task handler, and finally a host |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 false); | 233 false); |
| 234 } | 234 } |
| 235 } | 235 } |
| 236 } | 236 } |
| 237 | 237 |
| 238 LOG_IF(WARNING, !success) | 238 LOG_IF(WARNING, !success) |
| 239 << "SimulateCrash did not find an appropriate exception handler"; | 239 << "SimulateCrash did not find an appropriate exception handler"; |
| 240 } | 240 } |
| 241 | 241 |
| 242 } // namespace crashpad | 242 } // namespace crashpad |
| OLD | NEW |