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 |