ios: Add iOS crashpad overview documentation.

Adds an overview of the limitations of crashpad on the iOS platform,
including explanations of the in-process client and handler, and the
intermediate dump format used.

Bug: crashpad: 31
Change-Id: Ia70dc90067d882a7bdd9ffa524b187b6cce8fecf
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2706018
Commit-Queue: Justin Cohen <justincohen@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
GitOrigin-RevId: 2dbd019bc2303a0463a396b5c47b4eb16a1a1e27
diff --git a/client/crashpad_client.h b/client/crashpad_client.h
index cbe0551..ec6c5e5 100644
--- a/client/crashpad_client.h
+++ b/client/crashpad_client.h
@@ -485,18 +485,37 @@
   //! \brief Requests that the handler begin in-process uploading of any
   //! pending reports.
   //!
+  //! Once called the handler will start looking for pending reports to upload
+  //! on another thread. This method does not block.
+  //!
   //! A handler must have already been installed before calling this method.
-  void EnableUploading();
+  void StartProcesingPendingReports();
 
-  // TODO(justincohen): This method is purely for bringing up iOS interfaces.
-  //! \brief Requests that the handler capture a dump even though there hasn't
-  //!     been a crash.
+  //! \brief Requests that the handler capture an intermediate dump even though
+  //!     there hasn't been a crash. The intermediate dump will be converted
+  //!     to a mindump immediately. If StartProcesingPendingReports() has been
+  //!     called, this will also trigger an upload.
+  //!
+  //! For internal use only. Clients should use CRASHPAD_SIMULATE_CRASH().
   //!
   //! A handler must have already been installed before calling this method.
   //!
   //! \param[in] context A NativeCPUContext, generally captured by
   //!     CaptureContext() or similar.
   static void DumpWithoutCrash(NativeCPUContext* context);
+
+  //! \brief Requests that the handler capture an intermediate dump even though
+  //!     there hasn't been a crash. The intermediate dump will not be converted
+  //!     to a mindump until ProcessIntermediateDumps() is called.
+  //!
+  //! For internal use only. Clients should use
+  //! CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING().
+  //!
+  //! A handler must have already been installed before calling this method.
+  //!
+  //! \param[in] context A NativeCPUContext, generally captured by
+  //!     CaptureContext() or similar.
+  static void DumpWithoutCrashAndDeferProcessing(NativeCPUContext* context);
 #endif
 
 #if defined(OS_APPLE) || DOXYGEN
diff --git a/client/crashpad_client_ios.cc b/client/crashpad_client_ios.cc
index 588834c..6cbbb41 100644
--- a/client/crashpad_client_ios.cc
+++ b/client/crashpad_client_ios.cc
@@ -234,7 +234,7 @@
 }
 
 // static
-void CrashpadClient::EnableUploading() {
+void CrashpadClient::StartProcesingPendingReports() {
   // TODO(justincohen): Start the CrashReportUploadThread.
 }
 
@@ -243,7 +243,17 @@
   CrashHandler* crash_handler = CrashHandler::Get();
   DCHECK(crash_handler);
   crash_handler->DumpWithoutCrash(context);
+  // TODO(justincohen): Change this to only process the dump from above, not all
+  // intermediate dump files.
   crash_handler->ProcessIntermediateDumps();
 }
 
+// static
+void CrashpadClient::DumpWithoutCrashAndDeferProcessing(
+    NativeCPUContext* context) {
+  CrashHandler* crash_handler = CrashHandler::Get();
+  DCHECK(crash_handler);
+  crash_handler->DumpWithoutCrash(context);
+}
+
 }  // namespace crashpad
diff --git a/client/crashpad_client_ios_test.mm b/client/crashpad_client_ios_test.mm
index 5bc3946..30fabae 100644
--- a/client/crashpad_client_ios_test.mm
+++ b/client/crashpad_client_ios_test.mm
@@ -18,6 +18,7 @@
 
 #include <vector>
 
+#include "client/simulate_crash.h"
 #include "gtest/gtest.h"
 #include "test/scoped_temp_dir.h"
 #include "testing/platform_test.h"
@@ -33,9 +34,7 @@
   ScopedTempDir database_dir;
   client.StartCrashpadInProcessHandler(
       base::FilePath(database_dir.path()), "", {});
-  NativeCPUContext context;
-  CaptureContext(&context);
-  client.DumpWithoutCrash(&context);
+  CRASHPAD_SIMULATE_CRASH();
 }
 
 // This test is covered by a similar XCUITest, but for development purposes it's
diff --git a/client/simulate_crash_ios.h b/client/simulate_crash_ios.h
index 3cd1a69..87a9457 100644
--- a/client/simulate_crash_ios.h
+++ b/client/simulate_crash_ios.h
@@ -20,7 +20,11 @@
 
 //! \file
 
-//! \brief Captures the CPU context and captures a dump without an exception.
+//! \brief Captures the CPU context and creates a minidump dump without an
+//!     exception. The minidump will immediately become eligible for further
+//!     processing, including upload.
+//!
+//! \sa CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING
 #define CRASHPAD_SIMULATE_CRASH()                             \
   do {                                                        \
     crashpad::NativeCPUContext cpu_context;                   \
@@ -28,4 +32,19 @@
     crashpad::CrashpadClient::DumpWithoutCrash(&cpu_context); \
   } while (false)
 
+//! \brief Captures the CPU context and captures an intermediate dump without an
+//!     exception. Does not convert the intermediate dump into a minidump.
+//!
+//! Deferring processing is useful when the application may be in an unstable
+//! state, such as during a hang.
+//!
+//! \sa CRASHPAD_SIMULATE_CRASH
+#define CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING()            \
+  do {                                                            \
+    crashpad::NativeCPUContext cpu_context;                       \
+    crashpad::CaptureContext(&cpu_context);                       \
+    crashpad::CrashpadClient::DumpWithoutCrashAndDeferProcessing( \
+        &cpu_context);                                            \
+  } while (false)
+
 #endif  // CRASHPAD_CLIENT_SIMULATE_CRASH_IOS_H_
diff --git a/doc/ios_overview_design.md b/doc/ios_overview_design.md
new file mode 100644
index 0000000..be23d09
--- /dev/null
+++ b/doc/ios_overview_design.md
@@ -0,0 +1,104 @@
+<!--
+Copyright 2021 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.
+-->
+
+# iOS Crashpad Overview Design
+
+[TOC]
+
+## iOS Limitations
+
+Crashpad on other platforms captures exceptions out-of-process. The iOS sandbox,
+however, restricts applications from delegating work to separate processes.
+This limitation means Crashpad on iOS must combine the work of the handler and
+the client into the same process as the main application.
+
+## The Crashpad In-Process Handler
+
+In-process handling comes with a number of limitations and difficulties. It is
+not possible to catch the specific Mach exception `EXC_CRASH`, so certain groups
+of crashes cannot be captured. This includes some major ones, like out-of-memory
+crashes. This also introduces difficulties in capturing all the relevant crash
+data and writing the minidump, as the process itself is in an unsafe state.
+
+While handling an exception, the handler may not, for example:
+
+ - Allocate memory.
+ - Use libc, or most any library call.
+
+While handling an exception, the handler may only:
+
+ - Use audited syscalls.
+ - access memory via `vm_read`.
+
+In conjunction with Crashpad’s existing minidump writer and structural
+limitations of the minidump format, it is not possible to write a minidump
+immediately from the crash handler. Instead, an intermediate dump is written
+when a handler would normally write a minidump (such as during an exception or a
+forced dump without crashing).  The intermediate dump file will be converted to
+a minidump on the next run (or when the application decides it's safe to do so).
+
+During Crashpad initialization, the handler gathers basic system information
+and opens a pending intermediate dump adjacent to the Crashpad database.
+
+## The Crashpad IntermediateDump Format
+
+Due to the limitations of in-process handling, an intermediate dump file is
+written during exceptions. The data is streamed to a file, which will be used to
+generate a final minidump when appropriate.
+
+The file format is similar to binary JSON, supporting keyed properties, maps and
+arrays.
+
+ - `Property` [key:int, length:int, value:intarray]
+ - `StartMap` [key:int], followed by repeating Properties until `EndMap`
+ - `StartArray` [key:int], followed by repeating Maps until `EndArray`
+ - `EndMap`, `EndArray`, `EndDocument`
+
+Similar to JSON, maps can contain other maps, arrays and properties.
+
+## The Crashpad In-Process Client
+
+Other Crashpad platforms handle exceptions and upload minidumps out-of-process.
+On iOS, everything must happen in-process. Once started, the client will
+automatically handle exceptions and capture the crashed process state in an
+intermediate dump file. Converting that intermediate dump file into a minidump
+is likely not safe to do from within a crashed process, and uploading a minidump
+is definitely unsafe to do at crash time.  Applications are expected to process
+intermediate dumps into pending minidumps and begin processing pending
+minidumps, possibly for upload, at suitable times following the next application
+restart.
+
+
+### `ProcessIntermediateDumps`
+For performance and stability reasons applications may choose the correct time
+to convert intermediate dumps, as well as append metadata to the pending
+intermediate dumps. This is expected to happen during application startup, when
+suitable. After converting, a minidump will be written to the Crashpad database,
+similar to how other platforms write a minidump on exception handling. If
+uploading is enabled, this minidump will also be immediately uploaded. New
+intermediate dumps generated by exceptions or by
+`CRASHPAD_SIMULATE_CRASH_AND_DEFER_PROCESSING` will will not be processed until
+the next call to `ProcessIntermediateDumps`. Conversely,
+`CRASHPAD_SIMULATE_CRASH` can be called when the client has no performance or
+stability concerns.  In this case, intermediate dumps are automatically
+converted to minidumps and immediately eligable for uploading.
+
+### `StartProcesingPendingReports`
+For similar reasons, applications may choose the correct time to begin uploading
+pending reports, such as when ideal network conditions exist.  By default,
+clients start with uploading disabled.  Applications should call this API when
+it is determined that it is appropriate to do so (such as on a few seconds after
+startup, or when network connectivity is appropriate).
diff --git a/doc/overview_design.md b/doc/overview_design.md
index 9d0f0ed..01dba17 100644
--- a/doc/overview_design.md
+++ b/doc/overview_design.md
@@ -93,7 +93,8 @@
 responsible for snapshotting the crashing client process’ state on a crash,
 saving it to a crash dump, and transmitting the crash dump to an upstream
 server. Clients register with the handler to allow it to capture and upload
-their crashes.
+their crashes. On iOS, there is no separate process for the handler.
+[This is a limitation of iOS.](ios_overview_design.md#ios-limitations)
 
 ### The Crashpad handler
 
@@ -213,6 +214,12 @@
 existing crash handler, which can be necessary when an older client spawns an
 updated version.
 
+#### iOS
+
+iOS registers both a signal handler for `SIGABRT` and a Mach exception handler
+with a subset of available exceptions. [This is a limitation of
+iOS.](ios_overview_design.md#ios-limitations)
+
 #### Windows
 
 There are two modes of registration on Windows. In both cases the handler is
@@ -272,6 +279,14 @@
 entirely from the Crashpad handler without the need to run any code in the crash
 process at the time of the exception.
 
+#### iOS
+
+On iOS, the operating system will notify the handler of crashes via the Mach
+exception port or the signal handler. As exceptions are handled in-process, an
+intermediate dump file is generated rather than a minidump. See more
+information about the [iOS in-process
+handler.](ios_overview_design.md#ios-in-process-handler)
+
 #### Windows
 
 On Windows, the OS dispatches exceptions in the context of the crashing thread.
@@ -415,6 +430,14 @@
 The macOS implementation simply stores database properties on the minidump files
 in filesystem extended attributes.
 
+#### iOS
+
+The iOS implementation also stores database properties of minidump files in
+filesystem extended attributes. Separate from the database, iOS also stores its
+intermediate dump files adjacent to the database. See more information about
+[iOS intermediate
+dumps.](ios_overview_design.md#the-crashpad-intermediatedump-format)
+
 #### Windows
 
 The Windows implementation stores database properties in a binary file named