ios: Tighten up UIGestureEnvironment exception detection.

iOS 15.1 reordered private APIs before public APIs when looking at the
unw_get_proc_info() frame_info.start_ip, so doing a min/max within
UIGestureEnvironment would fail on devices. However, this API is always
called by UIWindow sendEvent, which is not a private API. Do the same
check, but instead look back 2 frames, and check to see if we are
within UIWindow.

Both APIs are still marked <redacted>, but the detection should still
work.

Also cleans up some tests fixtures when running in release.

Change-Id: I762615e9cb44389800cf3291af52a7568c3825d5
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3299008
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
diff --git a/client/ios_handler/exception_processor.mm b/client/ios_handler/exception_processor.mm
index ce1f268..1c05034 100644
--- a/client/ios_handler/exception_processor.mm
+++ b/client/ios_handler/exception_processor.mm
@@ -403,20 +403,22 @@
     // internally and also has has non-sinkhole handlers. While all the
     // calling methods in UIKit are marked <redacted> starting in iOS14, it's
     // currently true that all callers to _UIGestureEnvironmentUpdate are within
-    // UIGestureEnvironment.  That means a very hacky way to detect this are to
-    // check if the calling method IMP is within the range of all
-    // UIGestureEnvironment methods.
+    // UIWindow sendEvent -> UIGestureEnvironment.  That means a very hacky way
+    // to detect this is to check if the calling (2x) method IMP is within the
+    // range of all UIWindow methods.
     static constexpr const char kUIKitCorePath[] =
         "/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore";
     if (ModulePathMatchesSinkhole(dl_info.dli_fname, kUIKitCorePath)) {
       unw_proc_info_t caller_frame_info;
       if (LoggingUnwStep(&cursor) > 0 &&
+          unw_get_proc_info(&cursor, &caller_frame_info) == UNW_ESUCCESS &&
+          LoggingUnwStep(&cursor) > 0 &&
           unw_get_proc_info(&cursor, &caller_frame_info) == UNW_ESUCCESS) {
-        auto uigestureimp_lambda = [](IMP* max) {
+        auto uiwindowimp_lambda = [](IMP* max) {
           IMP min = *max = bit_cast<IMP>(nullptr);
           unsigned int method_count = 0;
           std::unique_ptr<Method[], base::FreeDeleter> method_list(
-              class_copyMethodList(NSClassFromString(@"UIGestureEnvironment"),
+              class_copyMethodList(NSClassFromString(@"UIWindow"),
                                    &method_count));
           if (method_count > 0) {
             min = *max = method_getImplementation(method_list[0]);
@@ -431,15 +433,14 @@
           return min;
         };
 
-        static IMP gesture_environment_max_imp;
-        static IMP gesture_environment_min_imp =
-            uigestureimp_lambda(&gesture_environment_max_imp);
+        static IMP uiwindow_max_imp;
+        static IMP uiwindow_min_imp = uiwindowimp_lambda(&uiwindow_max_imp);
 
-        if (gesture_environment_min_imp && gesture_environment_max_imp &&
+        if (uiwindow_min_imp && uiwindow_max_imp &&
             caller_frame_info.start_ip >=
-                reinterpret_cast<unw_word_t>(gesture_environment_min_imp) &&
+                reinterpret_cast<unw_word_t>(uiwindow_min_imp) &&
             caller_frame_info.start_ip <=
-                reinterpret_cast<unw_word_t>(gesture_environment_max_imp)) {
+                reinterpret_cast<unw_word_t>(uiwindow_max_imp)) {
           return HANDLE_UNCAUGHT_NSEXCEPTION(exception,
                                              "_UIGestureEnvironmentUpdate");
         }
diff --git a/test/ios/crash_type_xctest.mm b/test/ios/crash_type_xctest.mm
index 529ca13..2dcfac7 100644
--- a/test/ios/crash_type_xctest.mm
+++ b/test/ios/crash_type_xctest.mm
@@ -85,13 +85,9 @@
 
 - (void)testSegv {
   [rootObject_ crashSegv];
-#if defined(NDEBUG)
-#if TARGET_OS_SIMULATOR
+#if defined(NDEBUG) && TARGET_OS_SIMULATOR
   [self verifyCrashReportException:SIGINT];
 #else
-  [self verifyCrashReportException:SIGABRT];
-#endif
-#else
   [self verifyCrashReportException:SIGHUP];
 #endif
 }
@@ -117,13 +113,9 @@
 
 - (void)testBadAccess {
   [rootObject_ crashBadAccess];
-#if defined(NDEBUG)
-#if TARGET_OS_SIMULATOR
+#if defined(NDEBUG) && TARGET_OS_SIMULATOR
   [self verifyCrashReportException:SIGINT];
 #else
-  [self verifyCrashReportException:SIGABRT];
-#endif
-#else
   [self verifyCrashReportException:SIGHUP];
 #endif
 }
@@ -221,6 +213,7 @@
   XCTAssertTrue([dict[@"ver"] isEqualToString:@"42"]);
 }
 
+#if TARGET_OS_SIMULATOR
 - (void)testCrashWithCrashInfoMessage {
   if (@available(iOS 15.0, *)) {
     // Figure out how to test this on iOS15.
@@ -232,9 +225,10 @@
   NSString* dyldMessage = dict[@"vector"][0];
   XCTAssertTrue([dyldMessage isEqualToString:@"dyld: in dlsym()"]);
 }
+#endif
 
 // TODO(justincohen): Codesign crashy_initializer.so so it can run on devices.
-#if !TARGET_OS_SIMULATOR
+#if TARGET_OS_SIMULATOR
 - (void)testCrashWithDyldErrorString {
   if (@available(iOS 15.0, *)) {
     // iOS 15 uses dyld4, which doesn't use CRSetCrashLogMessage2