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, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "client/crashpad_client.h" | 15 #include "client/crashpad_client.h" |
16 | 16 |
17 #include <mach/mach.h> | 17 #include <mach/mach.h> |
18 #include <sys/wait.h> | 18 #include <sys/wait.h> |
19 #include <unistd.h> | 19 #include <unistd.h> |
20 | 20 |
21 #include "base/logging.h" | 21 #include "base/logging.h" |
22 #include "base/posix/eintr_wrapper.h" | 22 #include "base/posix/eintr_wrapper.h" |
23 #include "base/strings/stringprintf.h" | 23 #include "base/strings/stringprintf.h" |
24 #include "util/mach/child_port_handshake.h" | 24 #include "util/mach/child_port_handshake.h" |
25 #include "util/mach/exception_ports.h" | 25 #include "util/mach/exception_ports.h" |
26 #include "util/mach/mach_extensions.h" | 26 #include "util/mach/mach_extensions.h" |
27 #include "util/posix/close_multiple.h" | 27 #include "util/posix/close_multiple.h" |
28 | 28 |
| 29 namespace crashpad { |
| 30 |
29 namespace { | 31 namespace { |
30 | 32 |
31 std::string FormatArgumentString(const std::string& name, | 33 std::string FormatArgumentString(const std::string& name, |
32 const std::string& value) { | 34 const std::string& value) { |
33 return base::StringPrintf("--%s=%s", name.c_str(), value.c_str()); | 35 return base::StringPrintf("--%s=%s", name.c_str(), value.c_str()); |
34 } | 36 } |
35 | 37 |
36 std::string FormatArgumentInt(const std::string& name, int value) { | 38 std::string FormatArgumentInt(const std::string& name, int value) { |
37 return base::StringPrintf("--%s=%d", name.c_str(), value); | 39 return base::StringPrintf("--%s=%d", name.c_str(), value); |
38 } | 40 } |
39 | 41 |
| 42 // Set the exception handler for EXC_CRASH, EXC_RESOURCE, and EXC_GUARD. |
| 43 // |
| 44 // EXC_CRASH is how most crashes are received. Most other exception types such |
| 45 // as EXC_BAD_ACCESS are delivered to a host-level exception handler in the |
| 46 // kernel where they are converted to POSIX signals. See 10.9.5 |
| 47 // xnu-2422.115.4/bsd/uxkern/ux_exception.c catch_mach_exception_raise(). If a |
| 48 // core-generating signal (triggered through this hardware mechanism or a |
| 49 // software mechanism such as abort() sending SIGABRT) is unhandled and the |
| 50 // process exits, or if the process is killed with SIGKILL for code-signing |
| 51 // reasons, an EXC_CRASH exception will be sent. See 10.9.5 |
| 52 // xnu-2422.115.4/bsd/kern/kern_exit.c proc_prepareexit(). |
| 53 // |
| 54 // EXC_RESOURCE and EXC_GUARD do not become signals or EXC_CRASH exceptions. The |
| 55 // host-level exception handler in the kernel does not receive these exception |
| 56 // types, and even if it did, it would not map them to signals. Instead, the |
| 57 // first Mach service loaded by the root (process ID 1) launchd with a boolean |
| 58 // “ExceptionServer” property in its job dictionary (regardless of its value) or |
| 59 // with any subdictionary property will become the host-level exception handler |
| 60 // for EXC_CRASH, EXC_RESOURCE, and EXC_GUARD. See 10.9.5 |
| 61 // launchd-842.92.1/src/core.c job_setup_exception_port(). Normally, this job is |
| 62 // com.apple.ReportCrash.Root, the systemwide Apple Crash Reporter. Since it is |
| 63 // impossible to receive EXC_RESOURCE and EXC_GUARD exceptions through the |
| 64 // EXC_CRASH mechanism, an exception handler must be registered for them by name |
| 65 // if it is to receive these exception types. The default task-level handler for |
| 66 // these exception types is set by launchd in a similar manner. |
| 67 // |
| 68 // EXC_MASK_RESOURCE and EXC_MASK_GUARD are not available on all systems, and |
| 69 // the kernel will reject attempts to use them if it does not understand them, |
| 70 // so AND them with ExcMaskValid(). EXC_MASK_CRASH is always supported. |
| 71 bool SetCrashExceptionPorts(exception_handler_t exception_handler) { |
| 72 ExceptionPorts exception_ports(ExceptionPorts::kTargetTypeTask, TASK_NULL); |
| 73 return exception_ports.SetExceptionPort( |
| 74 (EXC_MASK_CRASH | EXC_MASK_RESOURCE | EXC_MASK_GUARD) & ExcMaskValid(), |
| 75 exception_handler, |
| 76 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, |
| 77 MACHINE_THREAD_STATE); |
| 78 } |
| 79 |
40 } // namespace | 80 } // namespace |
41 | 81 |
42 namespace crashpad { | |
43 | |
44 CrashpadClient::CrashpadClient() | 82 CrashpadClient::CrashpadClient() |
45 : exception_port_() { | 83 : exception_port_() { |
46 } | 84 } |
47 | 85 |
48 CrashpadClient::~CrashpadClient() { | 86 CrashpadClient::~CrashpadClient() { |
49 } | 87 } |
50 | 88 |
51 bool CrashpadClient::StartHandler( | 89 bool CrashpadClient::StartHandler( |
52 const base::FilePath& handler, | 90 const base::FilePath& handler, |
53 const base::FilePath& database, | 91 const base::FilePath& database, |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 210 |
173 // Rendezvous with the handler running in the grandchild process. | 211 // Rendezvous with the handler running in the grandchild process. |
174 exception_port_.reset(child_port_handshake.RunServer()); | 212 exception_port_.reset(child_port_handshake.RunServer()); |
175 | 213 |
176 return exception_port_ ? true : false; | 214 return exception_port_ ? true : false; |
177 } | 215 } |
178 | 216 |
179 bool CrashpadClient::UseHandler() { | 217 bool CrashpadClient::UseHandler() { |
180 DCHECK_NE(exception_port_, kMachPortNull); | 218 DCHECK_NE(exception_port_, kMachPortNull); |
181 | 219 |
182 // Set the exception handler for EXC_CRASH, EXC_RESOURCE, and EXC_GUARD. | 220 return SetCrashExceptionPorts(exception_port_); |
183 // | 221 } |
184 // EXC_CRASH is how most crashes are received. Most other exception types such | |
185 // as EXC_BAD_ACCESS are delivered to a host-level exception handler in the | |
186 // kernel where they are converted to POSIX signals. See 10.9.5 | |
187 // xnu-2422.115.4/bsd/uxkern/ux_exception.c catch_mach_exception_raise(). If a | |
188 // core-generating signal (triggered through this hardware mechanism or a | |
189 // software mechanism such as abort() sending SIGABRT) is unhandled and the | |
190 // process exits, or if the process is killed with SIGKILL for code-signing | |
191 // reasons, an EXC_CRASH exception will be sent. See 10.9.5 | |
192 // xnu-2422.115.4/bsd/kern/kern_exit.c proc_prepareexit(). | |
193 // | |
194 // EXC_RESOURCE and EXC_GUARD do not become signals or EXC_CRASH exceptions. | |
195 // The host-level exception handler in the kernel does not receive these | |
196 // exception types, and even if it did, it would not map them to signals. | |
197 // Instead, the first Mach service loaded by the root (process ID 1) launchd | |
198 // with a boolean “ExceptionServer” property in its job dictionary (regardless | |
199 // of its value) or with any subdictionary property will become the host-level | |
200 // exception handler for EXC_CRASH, EXC_RESOURCE, and EXC_GUARD. See 10.9.5 | |
201 // launchd-842.92.1/src/core.c job_setup_exception_port(). Normally, this job | |
202 // is com.apple.ReportCrash.Root, the systemwide Apple Crash Reporter. Since | |
203 // it is impossible to receive EXC_RESOURCE and EXC_GUARD exceptions through | |
204 // the EXC_CRASH mechanism, an exception handler must be registered for them | |
205 // by name if it is to receive these exception types. The default task-level | |
206 // handler for these exception types is set by launchd in a similar manner. | |
207 // | |
208 // EXC_MASK_RESOURCE and EXC_MASK_GUARD are not available on all systems, and | |
209 // the kernel will reject attempts to use them if it does not understand them, | |
210 // so AND them with ExcMaskValid(). EXC_MASK_CRASH is always supported. | |
211 ExceptionPorts exception_ports(ExceptionPorts::kTargetTypeTask, TASK_NULL); | |
212 if (!exception_ports.SetExceptionPort( | |
213 (EXC_MASK_CRASH | EXC_MASK_RESOURCE | EXC_MASK_GUARD) & | |
214 ExcMaskValid(), | |
215 exception_port_, | |
216 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, | |
217 MACHINE_THREAD_STATE)) { | |
218 return false; | |
219 } | |
220 | 222 |
221 return true; | 223 // static |
| 224 bool CrashpadClient::UseSystemDefaultHandler() { |
| 225 base::mac::ScopedMachSendRight |
| 226 system_crash_reporter_handler(SystemCrashReporterHandler()); |
| 227 |
| 228 // Proceed even if SystemCrashReporterHandler() failed, setting MACH_PORT_NULL |
| 229 // to clear the current exception ports. |
| 230 return SetCrashExceptionPorts(system_crash_reporter_handler); |
222 } | 231 } |
223 | 232 |
224 } // namespace crashpad | 233 } // namespace crashpad |
OLD | NEW |