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