| 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 |