| 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 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 ConstThreadState old_state, | 72 ConstThreadState old_state, |
| 73 mach_msg_type_number_t old_state_count, | 73 mach_msg_type_number_t old_state_count, |
| 74 thread_state_t new_state, | 74 thread_state_t new_state, |
| 75 mach_msg_type_number_t* new_state_count, | 75 mach_msg_type_number_t* new_state_count, |
| 76 const mach_msg_trailer_t* trailer, | 76 const mach_msg_trailer_t* trailer, |
| 77 bool* destroy_complex_request) override { | 77 bool* destroy_complex_request) override { |
| 78 *destroy_complex_request = true; | 78 *destroy_complex_request = true; |
| 79 ++*exceptions_handled_; | 79 ++*exceptions_handled_; |
| 80 | 80 |
| 81 fprintf(options_.file, | 81 fprintf(options_.file, |
| 82 "%s: behavior %s, ", | 82 "%s: behavior %s", |
| 83 me_.c_str(), | 83 me_.c_str(), |
| 84 ExceptionBehaviorToString( | 84 ExceptionBehaviorToString( |
| 85 behavior, kUseFullName | kUnknownIsNumeric | kUseOr).c_str()); | 85 behavior, kUseFullName | kUnknownIsNumeric | kUseOr).c_str()); |
| 86 | 86 |
| 87 kern_return_t kr; | 87 kern_return_t kr; |
| 88 if (ExceptionBehaviorHasIdentity(behavior)) { | 88 if (ExceptionBehaviorHasIdentity(behavior)) { |
| 89 pid_t pid; | 89 // It’s not possible to call pid_for_task() once EXC_CORPSE_NOTIFY has |
| 90 kr = pid_for_task(task, &pid); | 90 // been generated. It is possible to obtain the process ID by mapping the |
| 91 if (kr != KERN_SUCCESS) { | 91 // corpse kcdata area from the task’s address space at code[0] (size |
| 92 MACH_LOG(ERROR, kr) << "pid_for_task"; | 92 // code[1]) and locating TASK_CRASHINFO_PID within that area. This area |
| 93 return KERN_FAILURE; | 93 // also includes TASK_CRASHINFO_CRASHED_THREADID which could be used |
| 94 // instead of thread_info() below, and TASK_CRASHINFO_EXCEPTION_CODES |
| 95 // which could be used to recover the exception codes passed to the |
| 96 // EXC_CRASH handler. None of this is currently done because corpses are a |
| 97 // new 10.11-only feature. See 10.11 <corpses/task_corpse.h> and |
| 98 // <kern/kern_cdata.h>. |
| 99 if (exception != EXC_CORPSE_NOTIFY) { |
| 100 pid_t pid; |
| 101 kr = pid_for_task(task, &pid); |
| 102 if (kr != KERN_SUCCESS) { |
| 103 fprintf(options_.file, "\n"); |
| 104 fflush(options_.file); |
| 105 MACH_LOG(ERROR, kr) << "pid_for_task"; |
| 106 return KERN_FAILURE; |
| 107 } |
| 108 fprintf(options_.file, ", pid %d", pid); |
| 94 } | 109 } |
| 95 fprintf(options_.file, "pid %d, ", pid); | |
| 96 | 110 |
| 97 thread_identifier_info identifier_info; | 111 thread_identifier_info identifier_info; |
| 98 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; | 112 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; |
| 99 kr = thread_info(thread, | 113 kr = thread_info(thread, |
| 100 THREAD_IDENTIFIER_INFO, | 114 THREAD_IDENTIFIER_INFO, |
| 101 reinterpret_cast<thread_info_t>(&identifier_info), | 115 reinterpret_cast<thread_info_t>(&identifier_info), |
| 102 &count); | 116 &count); |
| 103 if (kr != KERN_SUCCESS) { | 117 if (kr != KERN_SUCCESS) { |
| 118 fprintf(options_.file, "\n"); |
| 119 fflush(options_.file); |
| 104 MACH_LOG(ERROR, kr) << "thread_info"; | 120 MACH_LOG(ERROR, kr) << "thread_info"; |
| 105 return KERN_FAILURE; | 121 return KERN_FAILURE; |
| 106 } | 122 } |
| 107 fprintf(options_.file, "thread %lld, ", identifier_info.thread_id); | 123 fprintf(options_.file, ", thread %lld", identifier_info.thread_id); |
| 108 } | 124 } |
| 109 | 125 |
| 110 fprintf( | 126 fprintf( |
| 111 options_.file, | 127 options_.file, |
| 112 "exception %s, codes[%d] ", | 128 ", exception %s, codes[%d]", |
| 113 ExceptionToString(exception, kUseFullName | kUnknownIsNumeric).c_str(), | 129 ExceptionToString(exception, kUseFullName | kUnknownIsNumeric).c_str(), |
| 114 code_count); | 130 code_count); |
| 115 | 131 |
| 116 for (size_t index = 0; index < code_count; ++index) { | 132 for (size_t index = 0; index < code_count; ++index) { |
| 117 fprintf(options_.file, | 133 fprintf(options_.file, |
| 118 "%#llx%s", | 134 "%s %#llx", |
| 119 code[index], | 135 index != 0 ? "," : "", |
| 120 index != code_count - 1 ? ", " : ""); | 136 code[index]); |
| 121 } | 137 } |
| 122 | 138 |
| 123 if (exception == EXC_CRASH) { | 139 if (exception == EXC_CRASH) { |
| 124 mach_exception_code_t original_code_0; | 140 mach_exception_code_t original_code_0; |
| 125 int signal; | 141 int signal; |
| 126 exception_type_t original_exception = | 142 exception_type_t original_exception = |
| 127 ExcCrashRecoverOriginalException(code[0], &original_code_0, &signal); | 143 ExcCrashRecoverOriginalException(code[0], &original_code_0, &signal); |
| 128 fprintf(options_.file, | 144 fprintf(options_.file, |
| 129 ", original exception %s, original code[0] %lld, signal %s", | 145 ", original exception %s, original code[0] %lld, signal %s", |
| 130 ExceptionToString(original_exception, | 146 ExceptionToString(original_exception, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 146 fflush(options_.file); | 162 fflush(options_.file); |
| 147 | 163 |
| 148 if (exception != EXC_CRASH && exception != kMachExceptionSimulated) { | 164 if (exception != EXC_CRASH && exception != kMachExceptionSimulated) { |
| 149 // Find another handler. | 165 // Find another handler. |
| 150 return KERN_FAILURE; | 166 return KERN_FAILURE; |
| 151 } | 167 } |
| 152 | 168 |
| 153 ExcServerCopyState( | 169 ExcServerCopyState( |
| 154 behavior, old_state, old_state_count, new_state, new_state_count); | 170 behavior, old_state, old_state_count, new_state, new_state_count); |
| 155 | 171 |
| 156 return ExcServerSuccessfulReturnValue(behavior, false); | 172 return ExcServerSuccessfulReturnValue(exception, behavior, false); |
| 157 } | 173 } |
| 158 | 174 |
| 159 private: | 175 private: |
| 160 const Options& options_; | 176 const Options& options_; |
| 161 const std::string& me_; | 177 const std::string& me_; |
| 162 int* exceptions_handled_; | 178 int* exceptions_handled_; |
| 163 }; | 179 }; |
| 164 | 180 |
| 165 void Usage(const std::string& me) { | 181 void Usage(const std::string& me) { |
| 166 fprintf(stderr, | 182 fprintf(stderr, |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 | 321 |
| 306 return EXIT_SUCCESS; | 322 return EXIT_SUCCESS; |
| 307 } | 323 } |
| 308 | 324 |
| 309 } // namespace | 325 } // namespace |
| 310 } // namespace crashpad | 326 } // namespace crashpad |
| 311 | 327 |
| 312 int main(int argc, char* argv[]) { | 328 int main(int argc, char* argv[]) { |
| 313 return crashpad::CatchExceptionToolMain(argc, argv); | 329 return crashpad::CatchExceptionToolMain(argc, argv); |
| 314 } | 330 } |
| OLD | NEW |