ios: Split bootstrap out from mach_extensions

mach_extensions is sensible on iOS, but bootstrap is not available
outside of macOS. To allow mach_extensions to be used cleanly on iOS,
the bootstrap code is moved into its own macOS-specific file.

Bug: crashpad:31
Change-Id: I30902bc18e71bf985160ff0e3acf5b84f03de853
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2154529
Reviewed-by: Justin Cohen <justincohen@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
GitOrigin-RevId: ba24acb86ca66277cc5fc7311961825850b04570
diff --git a/client/crashpad_client_mac.cc b/client/crashpad_client_mac.cc
index 22bd538..2fa8729 100644
--- a/client/crashpad_client_mac.cc
+++ b/client/crashpad_client_mac.cc
@@ -26,6 +26,7 @@
 #include "base/mac/mach_logging.h"
 #include "base/strings/stringprintf.h"
 #include "util/mac/mac_util.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/child_port_handshake.h"
 #include "util/mach/exception_ports.h"
 #include "util/mach/mach_extensions.h"
diff --git a/handler/handler_main.cc b/handler/handler_main.cc
index e0a262c..69da0f6 100644
--- a/handler/handler_main.cc
+++ b/handler/handler_main.cc
@@ -74,8 +74,8 @@
 #include "handler/mac/crash_report_exception_handler.h"
 #include "handler/mac/exception_handler_server.h"
 #include "handler/mac/file_limit_annotation.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/child_port_handshake.h"
-#include "util/mach/mach_extensions.h"
 #include "util/posix/close_stdio.h"
 #include "util/posix/signals.h"
 #elif defined(OS_WIN)
diff --git a/handler/mac/crash_report_exception_handler.cc b/handler/mac/crash_report_exception_handler.cc
index 9919e95..cccf1e9 100644
--- a/handler/mac/crash_report_exception_handler.cc
+++ b/handler/mac/crash_report_exception_handler.cc
@@ -28,6 +28,7 @@
 #include "snapshot/crashpad_info_client_options.h"
 #include "snapshot/mac/process_snapshot_mac.h"
 #include "util/file/file_writer.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/exc_client_variants.h"
 #include "util/mach/exception_behaviors.h"
 #include "util/mach/exception_types.h"
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 32dc298..047c786 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -57,14 +57,19 @@
     }
   }
 
+  if (crashpad_is_mac || crashpad_is_ios) {
+    sources += [
+      "mac/mach_errors.cc",
+      "mac/mach_errors.h",
+    ]
+  }
+
   if (crashpad_is_mac) {
     sources += [
       "mac/dyld.cc",
       "mac/dyld.h",
       "mac/exception_swallower.cc",
       "mac/exception_swallower.h",
-      "mac/mach_errors.cc",
-      "mac/mach_errors.h",
       "mac/mach_multiprocess.cc",
       "mac/mach_multiprocess.h",
     ]
diff --git a/test/mac/exception_swallower.cc b/test/mac/exception_swallower.cc
index 18c5cf7..946938f 100644
--- a/test/mac/exception_swallower.cc
+++ b/test/mac/exception_swallower.cc
@@ -24,6 +24,7 @@
 #include "base/mac/scoped_mach_port.h"
 #include "base/strings/stringprintf.h"
 #include "handler/mac/exception_handler_server.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/exc_server_variants.h"
 #include "util/mach/exception_ports.h"
 #include "util/mach/mach_extensions.h"
diff --git a/test/mac/mach_errors.cc b/test/mac/mach_errors.cc
index b68448f..db8ed66 100644
--- a/test/mac/mach_errors.cc
+++ b/test/mac/mach_errors.cc
@@ -14,8 +14,6 @@
 
 #include "test/mac/mach_errors.h"
 
-#include <servers/bootstrap.h>
-
 #include "base/strings/stringprintf.h"
 
 namespace {
@@ -50,28 +48,5 @@
                             FormatMachErrorNumber(mach_err).c_str());
 }
 
-std::string BootstrapErrorMessage(kern_return_t bootstrap_err,
-                                  const std::string& base) {
-  switch (bootstrap_err) {
-    case BOOTSTRAP_SUCCESS:
-    case BOOTSTRAP_NOT_PRIVILEGED:
-    case BOOTSTRAP_NAME_IN_USE:
-    case BOOTSTRAP_UNKNOWN_SERVICE:
-    case BOOTSTRAP_SERVICE_ACTIVE:
-    case BOOTSTRAP_BAD_COUNT:
-    case BOOTSTRAP_NO_MEMORY:
-    case BOOTSTRAP_NO_CHILDREN:
-      // Show known bootstrap errors in decimal because that's how they're
-      // defined in <servers/bootstrap.h>.
-      return base::StringPrintf("%s%s (%d)",
-                                FormatBase(base).c_str(),
-                                bootstrap_strerror(bootstrap_err),
-                                bootstrap_err);
-
-    default:
-      return MachErrorMessage(bootstrap_err, base);
-  }
-}
-
 }  // namespace test
 }  // namespace crashpad
diff --git a/test/mac/mach_errors.h b/test/mac/mach_errors.h
index 9e43ef2..0afcdad 100644
--- a/test/mac/mach_errors.h
+++ b/test/mac/mach_errors.h
@@ -22,9 +22,9 @@
 namespace crashpad {
 namespace test {
 
-// These functions format messages in a similar way to the logging macros in
-// base/mac/mach_logging.h. They exist to interoperate with gtest assertions,
-// which don’t interoperate with logging but can be streamed to.
+// This function formats messages in a similar way to the Mach error logging
+// macros in base/mac/mach_logging.h. It exists to interoperate with gtest
+// assertions, which don’t interoperate with logging but can be streamed to.
 //
 // Where non-test code could do:
 //   MACH_CHECK(kr == KERN_SUCCESS, kr) << "vm_deallocate";
@@ -47,23 +47,6 @@
 std::string MachErrorMessage(mach_error_t mach_err,
                              const std::string& base = std::string());
 
-//! \brief Formats a bootstrap error message.
-//!
-//! The returned string will combine the \a base string, if supplied, with a
-//! textual and numeric description of the error.
-//!
-//! \param[in] bootstrap_err The bootstrap error code.
-//! \param[in] base A string to prepend to the error description.
-//!
-//! \return A string of the format `"Permission denied (1100)"` if \a
-//!     bootstrap_err has the value `BOOTSTRAP_NOT_PRIVILEGED` on a system where
-//!     this is defined to be 1100. If \a base is not empty, it will be
-//!     prepended to this string, separated by a colon. If \a bootstrap_err is
-//!     not a valid bootstrap error code, it will be interpreted as a Mach error
-//!     code in the manner of MachErrorMessage().
-std::string BootstrapErrorMessage(kern_return_t bootstrap_err,
-                                  const std::string& base = std::string());
-
 }  // namespace test
 }  // namespace crashpad
 
diff --git a/test/mac/mach_multiprocess.cc b/test/mac/mach_multiprocess.cc
index f29a8b0..59aa653 100644
--- a/test/mac/mach_multiprocess.cc
+++ b/test/mac/mach_multiprocess.cc
@@ -27,6 +27,7 @@
 #include "test/errors.h"
 #include "test/mac/mach_errors.h"
 #include "util/file/file_io.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/mach_extensions.h"
 #include "util/mach/mach_message.h"
 #include "util/misc/implicit_cast.h"
diff --git a/tools/mac/catch_exception_tool.cc b/tools/mac/catch_exception_tool.cc
index d4dc3c1..4f40372 100644
--- a/tools/mac/catch_exception_tool.cc
+++ b/tools/mac/catch_exception_tool.cc
@@ -28,6 +28,7 @@
 #include "base/logging.h"
 #include "base/mac/mach_logging.h"
 #include "tools/tool_support.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/exc_server_variants.h"
 #include "util/mach/exception_behaviors.h"
 #include "util/mach/exception_types.h"
diff --git a/tools/mac/exception_port_tool.cc b/tools/mac/exception_port_tool.cc
index a047e96..b9d3fdd 100644
--- a/tools/mac/exception_port_tool.cc
+++ b/tools/mac/exception_port_tool.cc
@@ -30,6 +30,7 @@
 #include "base/macros.h"
 #include "base/strings/stringprintf.h"
 #include "tools/tool_support.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/exception_ports.h"
 #include "util/mach/mach_extensions.h"
 #include "util/mach/symbolic_constants_mach.h"
diff --git a/util/BUILD.gn b/util/BUILD.gn
index 7fe02f2..fdd2fe1 100644
--- a/util/BUILD.gn
+++ b/util/BUILD.gn
@@ -248,6 +248,8 @@
     sources += [
       "mac/xattr.cc",
       "mac/xattr.h",
+      "mach/mach_extensions.cc",
+      "mach/mach_extensions.h",
       "misc/clock_mac.cc",
       "misc/paths_mac.cc",
       "synchronization/semaphore_mac.cc",
@@ -263,6 +265,8 @@
       "mac/mac_util.h",
       "mac/service_management.cc",
       "mac/service_management.h",
+      "mach/bootstrap.cc",
+      "mach/bootstrap.h",
       "mach/child_port_handshake.cc",
       "mach/child_port_handshake.h",
       "mach/child_port_server.cc",
@@ -280,8 +284,6 @@
       "mach/exception_ports.h",
       "mach/exception_types.cc",
       "mach/exception_types.h",
-      "mach/mach_extensions.cc",
-      "mach/mach_extensions.h",
       "mach/mach_message.cc",
       "mach/mach_message.h",
       "mach/mach_message_server.cc",
@@ -659,7 +661,10 @@
   }
 
   if (crashpad_is_mac || crashpad_is_ios) {
-    sources += [ "mac/xattr_test.cc" ]
+    sources += [
+      "mac/xattr_test.cc",
+      "mach/mach_extensions_test.cc",
+    ]
   }
 
   if (crashpad_is_mac) {
@@ -667,6 +672,7 @@
       "mac/launchd_test.mm",
       "mac/mac_util_test.mm",
       "mac/service_management_test.mm",
+      "mach/bootstrap_test.cc",
       "mach/child_port_handshake_test.cc",
       "mach/child_port_server_test.cc",
       "mach/composite_mach_message_server_test.cc",
@@ -675,7 +681,6 @@
       "mach/exception_behaviors_test.cc",
       "mach/exception_ports_test.cc",
       "mach/exception_types_test.cc",
-      "mach/mach_extensions_test.cc",
       "mach/mach_message_server_test.cc",
       "mach/mach_message_test.cc",
       "mach/notify_server_test.cc",
diff --git a/util/mach/bootstrap.cc b/util/mach/bootstrap.cc
new file mode 100644
index 0000000..f553437
--- /dev/null
+++ b/util/mach/bootstrap.cc
@@ -0,0 +1,109 @@
+// Copyright 2020 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/mach/bootstrap.h"
+
+#include <mach/mach.h>
+#include <servers/bootstrap.h>
+
+#include "base/mac/mach_logging.h"
+
+namespace {
+
+// This forms the internal implementation for BootstrapCheckIn() and
+// BootstrapLookUp(), which follow the same logic aside from the routine called
+// and the right type returned.
+
+struct BootstrapCheckInTraits {
+  using Type = base::mac::ScopedMachReceiveRight;
+  static kern_return_t Call(mach_port_t bootstrap_port,
+                            const char* service_name,
+                            mach_port_t* service_port) {
+    return bootstrap_check_in(bootstrap_port, service_name, service_port);
+  }
+  static constexpr char kName[] = "bootstrap_check_in";
+};
+constexpr char BootstrapCheckInTraits::kName[];
+
+struct BootstrapLookUpTraits {
+  using Type = base::mac::ScopedMachSendRight;
+  static kern_return_t Call(mach_port_t bootstrap_port,
+                            const char* service_name,
+                            mach_port_t* service_port) {
+    return bootstrap_look_up(bootstrap_port, service_name, service_port);
+  }
+  static constexpr char kName[] = "bootstrap_look_up";
+};
+constexpr char BootstrapLookUpTraits::kName[];
+
+template <typename Traits>
+typename Traits::Type BootstrapCheckInOrLookUp(
+    const std::string& service_name) {
+  // bootstrap_check_in() and bootstrap_look_up() silently truncate service
+  // names longer than BOOTSTRAP_MAX_NAME_LEN. This check ensures that the name
+  // will not be truncated.
+  if (service_name.size() >= BOOTSTRAP_MAX_NAME_LEN) {
+    LOG(ERROR) << Traits::kName << " " << service_name << ": name too long";
+    return typename Traits::Type(MACH_PORT_NULL);
+  }
+
+  mach_port_t service_port;
+  kern_return_t kr =
+      Traits::Call(bootstrap_port, service_name.c_str(), &service_port);
+  if (kr != BOOTSTRAP_SUCCESS) {
+    BOOTSTRAP_LOG(ERROR, kr) << Traits::kName << " " << service_name;
+    service_port = MACH_PORT_NULL;
+  }
+
+  return typename Traits::Type(service_port);
+}
+
+}  // namespace
+
+namespace crashpad {
+
+base::mac::ScopedMachReceiveRight BootstrapCheckIn(
+    const std::string& service_name) {
+  return BootstrapCheckInOrLookUp<BootstrapCheckInTraits>(service_name);
+}
+
+base::mac::ScopedMachSendRight BootstrapLookUp(
+    const std::string& service_name) {
+  base::mac::ScopedMachSendRight send(
+      BootstrapCheckInOrLookUp<BootstrapLookUpTraits>(service_name));
+
+  // It’s possible to race the bootstrap server when the receive right
+  // corresponding to the looked-up send right is destroyed immediately before
+  // the bootstrap_look_up() call. If the bootstrap server believes that
+  // |service_name| is still registered before processing the port-destroyed
+  // notification sent to it by the kernel, it will respond to a
+  // bootstrap_look_up() request with a send right that has become a dead name,
+  // which will be returned to the bootstrap_look_up() caller, translated into
+  // the caller’s IPC port name space, as the special MACH_PORT_DEAD port name.
+  // Check for that and return MACH_PORT_NULL in its place, as though the
+  // bootstrap server had fully processed the port-destroyed notification before
+  // responding to bootstrap_look_up().
+  if (send.get() == MACH_PORT_DEAD) {
+    LOG(ERROR) << "bootstrap_look_up " << service_name << ": service is dead";
+    send.reset();
+  }
+
+  return send;
+}
+
+base::mac::ScopedMachSendRight SystemCrashReporterHandler() {
+  return BootstrapLookUp("com.apple.ReportCrash");
+}
+
+}  // namespace crashpad
diff --git a/util/mach/bootstrap.h b/util/mach/bootstrap.h
new file mode 100644
index 0000000..680f5b9
--- /dev/null
+++ b/util/mach/bootstrap.h
@@ -0,0 +1,63 @@
+// Copyright 2020 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CRASHPAD_UTIL_MACH_BOOTSTRAP_H_
+#define CRASHPAD_UTIL_MACH_BOOTSTRAP_H_
+
+#include <string>
+
+#include "base/mac/scoped_mach_port.h"
+
+namespace crashpad {
+
+//! \brief Makes a `boostrap_check_in()` call to the process’ bootstrap server.
+//!
+//! This function is provided to make it easier to call `bootstrap_check_in()`
+//! while avoiding accidental leaks of the returned receive right.
+//!
+//! \param[in] service_name The service name to check in.
+//!
+//! \return On success, a receive right to the service port. On failure,
+//!     `MACH_PORT_NULL` with a message logged.
+base::mac::ScopedMachReceiveRight BootstrapCheckIn(
+    const std::string& service_name);
+
+//! \brief Makes a `boostrap_look_up()` call to the process’ bootstrap server.
+//!
+//! This function is provided to make it easier to call `bootstrap_look_up()`
+//! while avoiding accidental leaks of the returned send right.
+//!
+//! \param[in] service_name The service name to look up.
+//!
+//! \return On success, a send right to the service port. On failure,
+//!     `MACH_PORT_NULL` with a message logged.
+base::mac::ScopedMachSendRight BootstrapLookUp(const std::string& service_name);
+
+//! \brief Obtains the system’s default Mach exception handler for crash-type
+//!     exceptions.
+//!
+//! This is obtained by looking up `"com.apple.ReportCrash"` with the bootstrap
+//! server. The service name comes from the first launch agent loaded by
+//! `launchd` with a `MachServices` entry having `ExceptionServer` set. This
+//! launch agent is normally loaded from
+//! `/System/Library/LaunchAgents/com.apple.ReportCrash.plist`.
+//!
+//! \return On success, a send right to an `exception_handler_t` corresponding
+//!     to the system’s default crash reporter. On failure, `MACH_PORT_NULL`,
+//!     with a message logged.
+base::mac::ScopedMachSendRight SystemCrashReporterHandler();
+
+}  // namespace crashpad
+
+#endif  // CRASHPAD_UTIL_MACH_BOOTSTRAP_H_
diff --git a/util/mach/bootstrap_test.cc b/util/mach/bootstrap_test.cc
new file mode 100644
index 0000000..44587d0
--- /dev/null
+++ b/util/mach/bootstrap_test.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "util/mach/bootstrap.h"
+
+#include "base/mac/scoped_mach_port.h"
+#include "gtest/gtest.h"
+#include "util/mach/mach_extensions.h"
+#include "util/misc/random_string.h"
+
+namespace crashpad {
+namespace test {
+namespace {
+
+TEST(Bootstrap, BootstrapCheckInAndLookUp) {
+  // This should always exist.
+  base::mac::ScopedMachSendRight report_crash(
+      BootstrapLookUp("com.apple.ReportCrash"));
+  EXPECT_NE(report_crash, kMachPortNull);
+
+  std::string service_name = "org.chromium.crashpad.test.bootstrap_check_in.";
+  service_name.append(RandomString());
+
+  {
+    // The new service hasn’t checked in yet, so this should fail.
+    base::mac::ScopedMachSendRight send(BootstrapLookUp(service_name));
+    EXPECT_EQ(send, kMachPortNull);
+
+    // Check it in.
+    base::mac::ScopedMachReceiveRight receive(BootstrapCheckIn(service_name));
+    EXPECT_NE(receive, kMachPortNull);
+
+    // Now it should be possible to look up the new service.
+    send = BootstrapLookUp(service_name);
+    EXPECT_NE(send, kMachPortNull);
+
+    // It shouldn’t be possible to check the service in while it’s active.
+    base::mac::ScopedMachReceiveRight receive_2(BootstrapCheckIn(service_name));
+    EXPECT_EQ(receive_2, kMachPortNull);
+  }
+
+  // The new service should be gone now.
+  base::mac::ScopedMachSendRight send(BootstrapLookUp(service_name));
+  EXPECT_EQ(send, kMachPortNull);
+
+  // It should be possible to check it in again.
+  base::mac::ScopedMachReceiveRight receive(BootstrapCheckIn(service_name));
+  EXPECT_NE(receive, kMachPortNull);
+}
+
+TEST(Bootstrap, SystemCrashReporterHandler) {
+  base::mac::ScopedMachSendRight system_crash_reporter_handler(
+      SystemCrashReporterHandler());
+  EXPECT_TRUE(system_crash_reporter_handler.is_valid());
+}
+
+}  // namespace
+}  // namespace test
+}  // namespace crashpad
diff --git a/util/mach/child_port_handshake.cc b/util/mach/child_port_handshake.cc
index 1891f91..3ff9828 100644
--- a/util/mach/child_port_handshake.cc
+++ b/util/mach/child_port_handshake.cc
@@ -34,6 +34,7 @@
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "util/file/file_io.h"
+#include "util/mach/bootstrap.h"
 #include "util/mach/child_port.h"
 #include "util/mach/child_port_server.h"
 #include "util/mach/mach_extensions.h"
diff --git a/util/mach/mach_extensions.cc b/util/mach/mach_extensions.cc
index 5450ab2..9e31012 100644
--- a/util/mach/mach_extensions.cc
+++ b/util/mach/mach_extensions.cc
@@ -14,66 +14,14 @@
 
 #include "util/mach/mach_extensions.h"
 
+#include <Availability.h>
 #include <AvailabilityMacros.h>
 #include <pthread.h>
-#include <servers/bootstrap.h>
 
 #include "base/mac/mach_logging.h"
+#include "build/build_config.h"
 #include "util/mac/mac_util.h"
 
-namespace {
-
-// This forms the internal implementation for BootstrapCheckIn() and
-// BootstrapLookUp(), which follow the same logic aside from the routine called
-// and the right type returned.
-
-struct BootstrapCheckInTraits {
-  using Type = base::mac::ScopedMachReceiveRight;
-  static kern_return_t Call(mach_port_t bootstrap_port,
-                            const char* service_name,
-                            mach_port_t* service_port) {
-    return bootstrap_check_in(bootstrap_port, service_name, service_port);
-  }
-  static constexpr char kName[] = "bootstrap_check_in";
-};
-constexpr char BootstrapCheckInTraits::kName[];
-
-struct BootstrapLookUpTraits {
-  using Type = base::mac::ScopedMachSendRight;
-  static kern_return_t Call(mach_port_t bootstrap_port,
-                            const char* service_name,
-                            mach_port_t* service_port) {
-    return bootstrap_look_up(bootstrap_port, service_name, service_port);
-  }
-  static constexpr char kName[] = "bootstrap_look_up";
-};
-constexpr char BootstrapLookUpTraits::kName[];
-
-template <typename Traits>
-typename Traits::Type BootstrapCheckInOrLookUp(
-    const std::string& service_name) {
-  // bootstrap_check_in() and bootstrap_look_up() silently truncate service
-  // names longer than BOOTSTRAP_MAX_NAME_LEN. This check ensures that the name
-  // will not be truncated.
-  if (service_name.size() >= BOOTSTRAP_MAX_NAME_LEN) {
-    LOG(ERROR) << Traits::kName << " " << service_name << ": name too long";
-    return typename Traits::Type(MACH_PORT_NULL);
-  }
-
-  mach_port_t service_port;
-  kern_return_t kr = Traits::Call(bootstrap_port,
-                                  service_name.c_str(),
-                                  &service_port);
-  if (kr != BOOTSTRAP_SUCCESS) {
-    BOOTSTRAP_LOG(ERROR, kr) << Traits::kName << " " << service_name;
-    service_port = MACH_PORT_NULL;
-  }
-
-  return typename Traits::Type(service_port);
-}
-
-}  // namespace
-
 namespace crashpad {
 
 thread_t MachThreadSelf() {
@@ -97,7 +45,12 @@
   // 10.9.4 xnu-2422.110.17/osfmk/mach/ipc_host.c and
   // xnu-2422.110.17/osfmk/mach/ipc_tt.c.
 
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
+#if defined(OS_IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
+// iOS 7 ≅ macOS 10.9.
+#error This code was not ported to iOS versions older than 7
+#endif
+
+#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
   const int mac_os_x_minor_version = MacOSXMinorVersion();
 #endif
 
@@ -114,7 +67,7 @@
       EXC_MASK_MACH_SYSCALL |
       EXC_MASK_RPC_ALERT |
       EXC_MASK_MACHINE;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
+#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
   if (mac_os_x_minor_version < 8) {
     return kExcMaskAll_10_6;
   }
@@ -124,7 +77,7 @@
   // xnu-2050.48.11/osfmk/mach/exception_types.h.
   constexpr exception_mask_t kExcMaskAll_10_8 =
       kExcMaskAll_10_6 | EXC_MASK_RESOURCE;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
+#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
   if (mac_os_x_minor_version < 9) {
     return kExcMaskAll_10_8;
   }
@@ -139,7 +92,12 @@
 
 exception_mask_t ExcMaskValid() {
   const exception_mask_t kExcMaskValid_10_6 = ExcMaskAll() | EXC_MASK_CRASH;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11
+#if defined(OS_IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0
+// iOS 9 ≅ macOS 10.11.
+#error This code was not ported to iOS versions older than 9
+#endif
+
+#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11
   if (MacOSXMinorVersion() < 11) {
     return kExcMaskValid_10_6;
   }
@@ -151,37 +109,4 @@
   return kExcMaskValid_10_11;
 }
 
-base::mac::ScopedMachReceiveRight BootstrapCheckIn(
-    const std::string& service_name) {
-  return BootstrapCheckInOrLookUp<BootstrapCheckInTraits>(service_name);
-}
-
-base::mac::ScopedMachSendRight BootstrapLookUp(
-    const std::string& service_name) {
-  base::mac::ScopedMachSendRight send(
-      BootstrapCheckInOrLookUp<BootstrapLookUpTraits>(service_name));
-
-  // It’s possible to race the bootstrap server when the receive right
-  // corresponding to the looked-up send right is destroyed immediately before
-  // the bootstrap_look_up() call. If the bootstrap server believes that
-  // |service_name| is still registered before processing the port-destroyed
-  // notification sent to it by the kernel, it will respond to a
-  // bootstrap_look_up() request with a send right that has become a dead name,
-  // which will be returned to the bootstrap_look_up() caller, translated into
-  // the caller’s IPC port name space, as the special MACH_PORT_DEAD port name.
-  // Check for that and return MACH_PORT_NULL in its place, as though the
-  // bootstrap server had fully processed the port-destroyed notification before
-  // responding to bootstrap_look_up().
-  if (send.get() == MACH_PORT_DEAD) {
-    LOG(ERROR) << "bootstrap_look_up " << service_name << ": service is dead";
-    send.reset();
-  }
-
-  return send;
-}
-
-base::mac::ScopedMachSendRight SystemCrashReporterHandler() {
-  return BootstrapLookUp("com.apple.ReportCrash");
-}
-
 }  // namespace crashpad
diff --git a/util/mach/mach_extensions.h b/util/mach/mach_extensions.h
index 25e401c..9247ce9 100644
--- a/util/mach/mach_extensions.h
+++ b/util/mach/mach_extensions.h
@@ -17,10 +17,6 @@
 
 #include <mach/mach.h>
 
-#include <string>
-
-#include "base/mac/scoped_mach_port.h"
-
 namespace crashpad {
 
 //! \brief `MACH_PORT_NULL` with the correct type for a Mach port,
@@ -119,43 +115,6 @@
 //! support is present.
 exception_mask_t ExcMaskValid();
 
-//! \brief Makes a `boostrap_check_in()` call to the process’ bootstrap server.
-//!
-//! This function is provided to make it easier to call `bootstrap_check_in()`
-//! while avoiding accidental leaks of the returned receive right.
-//!
-//! \param[in] service_name The service name to check in.
-//!
-//! \return On success, a receive right to the service port. On failure,
-//!     `MACH_PORT_NULL` with a message logged.
-base::mac::ScopedMachReceiveRight BootstrapCheckIn(
-    const std::string& service_name);
-
-//! \brief Makes a `boostrap_look_up()` call to the process’ bootstrap server.
-//!
-//! This function is provided to make it easier to call `bootstrap_look_up()`
-//! while avoiding accidental leaks of the returned send right.
-//!
-//! \param[in] service_name The service name to look up.
-//!
-//! \return On success, a send right to the service port. On failure,
-//!     `MACH_PORT_NULL` with a message logged.
-base::mac::ScopedMachSendRight BootstrapLookUp(const std::string& service_name);
-
-//! \brief Obtains the system’s default Mach exception handler for crash-type
-//!     exceptions.
-//!
-//! This is obtained by looking up `"com.apple.ReportCrash"` with the bootstrap
-//! server. The service name comes from the first launch agent loaded by
-//! `launchd` with a `MachServices` entry having `ExceptionServer` set. This
-//! launch agent is normally loaded from
-//! `/System/Library/LaunchAgents/com.apple.ReportCrash.plist`.
-//!
-//! \return On success, a send right to an `exception_handler_t` corresponding
-//!     to the system’s default crash reporter. On failure, `MACH_PORT_NULL`,
-//!     with a message logged.
-base::mac::ScopedMachSendRight SystemCrashReporterHandler();
-
 }  // namespace crashpad
 
 #endif  // CRASHPAD_UTIL_MACH_MACH_EXTENSIONS_H_
diff --git a/util/mach/mach_extensions_test.cc b/util/mach/mach_extensions_test.cc
index 1c5b368..748e0aa 100644
--- a/util/mach/mach_extensions_test.cc
+++ b/util/mach/mach_extensions_test.cc
@@ -15,10 +15,10 @@
 #include "util/mach/mach_extensions.h"
 
 #include "base/mac/scoped_mach_port.h"
+#include "build/build_config.h"
 #include "gtest/gtest.h"
 #include "test/mac/mach_errors.h"
 #include "util/mac/mac_util.h"
-#include "util/misc/random_string.h"
 
 namespace crashpad {
 namespace test {
@@ -80,6 +80,11 @@
   EXPECT_FALSE(exc_mask_all & EXC_MASK_CRASH);
   EXPECT_FALSE(exc_mask_all & EXC_MASK_CORPSE_NOTIFY);
 
+#if defined(OS_IOS)
+  // Assume at least iOS 7 (≅ macOS 10.9).
+  EXPECT_TRUE(exc_mask_all & EXC_MASK_RESOURCE);
+  EXPECT_TRUE(exc_mask_all & EXC_MASK_GUARD);
+#else  // OS_IOS
   const int mac_os_x_minor_version = MacOSXMinorVersion();
   if (mac_os_x_minor_version >= 8) {
     EXPECT_TRUE(exc_mask_all & EXC_MASK_RESOURCE);
@@ -92,6 +97,7 @@
   } else {
     EXPECT_FALSE(exc_mask_all & EXC_MASK_GUARD);
   }
+#endif  // OS_IOS
 
   // Bit 0 should not be set.
   EXPECT_FALSE(ExcMaskAll() & 1);
@@ -106,6 +112,12 @@
 
   EXPECT_TRUE(exc_mask_valid & EXC_MASK_CRASH);
 
+#if defined(OS_IOS)
+  // Assume at least iOS 9 (≅ macOS 10.11).
+  EXPECT_TRUE(exc_mask_valid & EXC_MASK_RESOURCE);
+  EXPECT_TRUE(exc_mask_valid & EXC_MASK_GUARD);
+  EXPECT_TRUE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY);
+#else  // OS_IOS
   const int mac_os_x_minor_version = MacOSXMinorVersion();
   if (mac_os_x_minor_version >= 8) {
     EXPECT_TRUE(exc_mask_valid & EXC_MASK_RESOURCE);
@@ -124,6 +136,7 @@
   } else {
     EXPECT_FALSE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY);
   }
+#endif  // OS_IOS
 
   // Bit 0 should not be set.
   EXPECT_FALSE(ExcMaskValid() & 1);
@@ -132,48 +145,6 @@
   EXPECT_TRUE(ExcMaskValid() & ~ExcMaskAll());
 }
 
-TEST(MachExtensions, BootstrapCheckInAndLookUp) {
-  // This should always exist.
-  base::mac::ScopedMachSendRight
-      report_crash(BootstrapLookUp("com.apple.ReportCrash"));
-  EXPECT_NE(report_crash, kMachPortNull);
-
-  std::string service_name = "org.chromium.crashpad.test.bootstrap_check_in.";
-  service_name.append(RandomString());
-
-  {
-    // The new service hasn’t checked in yet, so this should fail.
-    base::mac::ScopedMachSendRight send(BootstrapLookUp(service_name));
-    EXPECT_EQ(send, kMachPortNull);
-
-    // Check it in.
-    base::mac::ScopedMachReceiveRight receive(BootstrapCheckIn(service_name));
-    EXPECT_NE(receive, kMachPortNull);
-
-    // Now it should be possible to look up the new service.
-    send = BootstrapLookUp(service_name);
-    EXPECT_NE(send, kMachPortNull);
-
-    // It shouldn’t be possible to check the service in while it’s active.
-    base::mac::ScopedMachReceiveRight receive_2(BootstrapCheckIn(service_name));
-    EXPECT_EQ(receive_2, kMachPortNull);
-  }
-
-  // The new service should be gone now.
-  base::mac::ScopedMachSendRight send(BootstrapLookUp(service_name));
-  EXPECT_EQ(send, kMachPortNull);
-
-  // It should be possible to check it in again.
-  base::mac::ScopedMachReceiveRight receive(BootstrapCheckIn(service_name));
-  EXPECT_NE(receive, kMachPortNull);
-}
-
-TEST(MachExtensions, SystemCrashReporterHandler) {
-  base::mac::ScopedMachSendRight
-      system_crash_reporter_handler(SystemCrashReporterHandler());
-  EXPECT_TRUE(system_crash_reporter_handler.is_valid());
-}
-
 }  // namespace
 }  // namespace test
 }  // namespace crashpad