diff --git a/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc b/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc index c4d99e77..a45d4cc2 100644 --- a/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc +++ b/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc @@ -131,10 +131,16 @@ bool ExceptionSnapshotIOSIntermediateDump::InitializeFromSignal( #endif } - GetDataValueFromMap(exception_data, Key::kSignalNumber, &exception_); - GetDataValueFromMap(exception_data, Key::kSignalCode, &exception_info_); + exception_ = EXC_SOFT_SIGNAL; + GetDataValueFromMap(exception_data, Key::kSignalNumber, &exception_info_); GetDataValueFromMap(exception_data, Key::kSignalAddress, &exception_address_); + codes_.push_back(exception_); + codes_.push_back(exception_info_); + uint32_t code; + GetDataValueFromMap(exception_data, Key::kSignalCode, &code); + codes_.push_back(code); + INITIALIZATION_STATE_SET_VALID(initialized_); return true; } diff --git a/test/ios/crash_type_xctest.mm b/test/ios/crash_type_xctest.mm index 2dcfac78..3613e220 100644 --- a/test/ios/crash_type_xctest.mm +++ b/test/ios/crash_type_xctest.mm @@ -65,7 +65,7 @@ XCTAssertTrue(app_.state == XCUIApplicationStateRunningForeground); } -- (void)verifyCrashReportException:(int)exception { +- (void)verifyCrashReportException:(uint32_t)exception { // Confirm the app is not running. XCTAssertTrue([app_ waitForState:XCUIApplicationStateNotRunning timeout:15]); XCTAssertTrue(app_.state == XCUIApplicationStateNotRunning); @@ -75,7 +75,9 @@ XCTAssertTrue(app_.state == XCUIApplicationStateRunningForeground); rootObject_ = [EDOClientService rootObjectWithPort:12345]; XCTAssertEqual([rootObject_ pendingReportCount], 1); - XCTAssertEqual([rootObject_ pendingReportException], exception); + NSNumber* report_exception; + XCTAssertTrue([rootObject_ pendingReportException:&report_exception]); + XCTAssertEqual(report_exception.unsignedIntValue, exception); } - (void)testEDO { @@ -85,44 +87,61 @@ - (void)testSegv { [rootObject_ crashSegv]; -#if defined(NDEBUG) && TARGET_OS_SIMULATOR - [self verifyCrashReportException:SIGINT]; +#if defined(NDEBUG) +#if TARGET_OS_SIMULATOR + [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; #else - [self verifyCrashReportException:SIGHUP]; + [self verifyCrashReportException:EXC_BREAKPOINT]; +#endif +#else + [self verifyCrashReportException:EXC_BAD_ACCESS]; #endif } - (void)testKillAbort { [rootObject_ crashKillAbort]; - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_SOFT_SIGNAL]; + NSNumber* report_exception; + XCTAssertTrue([rootObject_ pendingReportExceptionInfo:&report_exception]); + XCTAssertEqual(report_exception.intValue, SIGABRT); } - (void)testTrap { [rootObject_ crashTrap]; #if TARGET_OS_SIMULATOR - [self verifyCrashReportException:SIGINT]; + [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; #else - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_BREAKPOINT]; #endif } - (void)testAbort { [rootObject_ crashAbort]; - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_SOFT_SIGNAL]; + NSNumber* report_exception; + XCTAssertTrue([rootObject_ pendingReportExceptionInfo:&report_exception]); + XCTAssertEqual(report_exception.intValue, SIGABRT); } - (void)testBadAccess { [rootObject_ crashBadAccess]; -#if defined(NDEBUG) && TARGET_OS_SIMULATOR - [self verifyCrashReportException:SIGINT]; +#if defined(NDEBUG) +#if TARGET_OS_SIMULATOR + [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; #else - [self verifyCrashReportException:SIGHUP]; + [self verifyCrashReportException:EXC_BREAKPOINT]; +#endif +#else + [self verifyCrashReportException:EXC_BAD_ACCESS]; #endif } - (void)testException { [rootObject_ crashException]; - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_SOFT_SIGNAL]; + NSNumber* report_exception; + XCTAssertTrue([rootObject_ pendingReportExceptionInfo:&report_exception]); + XCTAssertEqual(report_exception.intValue, SIGABRT); } - (void)testNSException { @@ -183,7 +202,7 @@ - (void)testRecursion { [rootObject_ crashRecursion]; - [self verifyCrashReportException:SIGHUP]; + [self verifyCrashReportException:EXC_BAD_ACCESS]; } - (void)testClientAnnotations { @@ -192,7 +211,11 @@ // Set app launch args to trigger different client annotations. NSArray* old_args = app_.launchArguments; app_.launchArguments = @[ @"--alternate-client-annotations" ]; - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_SOFT_SIGNAL]; + NSNumber* report_exception; + XCTAssertTrue([rootObject_ pendingReportExceptionInfo:&report_exception]); + XCTAssertEqual(report_exception.intValue, SIGABRT); + app_.launchArguments = old_args; // Confirm the initial crash took the standard annotations. @@ -205,7 +228,10 @@ // Confirm passing alternate client annotation args works. [rootObject_ clearPendingReports]; [rootObject_ crashKillAbort]; - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_SOFT_SIGNAL]; + XCTAssertTrue([rootObject_ pendingReportExceptionInfo:&report_exception]); + XCTAssertEqual(report_exception.intValue, SIGABRT); + dict = [rootObject_ getProcessAnnotations]; XCTAssertTrue([dict[@"crashpad"] isEqualToString:@"no"]); XCTAssertTrue([dict[@"plat"] isEqualToString:@"macOS"]); @@ -220,7 +246,7 @@ return; } [rootObject_ crashWithCrashInfoMessage]; - [self verifyCrashReportException:SIGHUP]; + [self verifyCrashReportException:EXC_BAD_ACCESS]; NSDictionary* dict = [rootObject_ getAnnotations]; NSString* dyldMessage = dict[@"vector"][0]; XCTAssertTrue([dyldMessage isEqualToString:@"dyld: in dlsym()"]); @@ -235,7 +261,7 @@ return; } [rootObject_ crashWithDyldErrorString]; - [self verifyCrashReportException:SIGINT]; + [self verifyCrashReportException:EXC_BAD_INSTRUCTION]; NSArray* vector = [rootObject_ getAnnotations][@"vector"]; // This message is set by dyld-353.2.1/src/ImageLoaderMachO.cpp // ImageLoaderMachO::doInitialization(). @@ -246,7 +272,11 @@ - (void)testCrashWithAnnotations { [rootObject_ crashWithAnnotations]; - [self verifyCrashReportException:SIGABRT]; + [self verifyCrashReportException:EXC_SOFT_SIGNAL]; + NSNumber* report_exception; + XCTAssertTrue([rootObject_ pendingReportExceptionInfo:&report_exception]); + XCTAssertEqual(report_exception.intValue, SIGABRT); + NSDictionary* dict = [rootObject_ getAnnotations]; NSDictionary* simpleMap = dict[@"simplemap"]; XCTAssertTrue([simpleMap[@"#TEST# empty_value"] isEqualToString:@""]); diff --git a/test/ios/host/cptest_application_delegate.mm b/test/ios/host/cptest_application_delegate.mm index 44a7d88a..3bf39dfe 100644 --- a/test/ios/host/cptest_application_delegate.mm +++ b/test/ios/host/cptest_application_delegate.mm @@ -68,6 +68,24 @@ OperationStatus GetPendingReports(std::vector* pending_reports) { return database->GetPendingReports(pending_reports); } +std::unique_ptr +GetProcessSnapshotMinidumpFromSinglePending() { + std::vector pending_reports; + OperationStatus status = GetPendingReports(&pending_reports); + if (status != crashpad::CrashReportDatabase::kNoError || + pending_reports.size() != 1) { + return nullptr; + } + + auto reader = std::make_unique(); + auto process_snapshot = std::make_unique(); + if (!reader->Open(pending_reports[0].file_path) || + !process_snapshot->Initialize(reader.get())) { + return nullptr; + } + return process_snapshot; +} + [[clang::optnone]] void recurse(int counter) { // Fill up the stack faster. int arr[1024]; @@ -159,40 +177,36 @@ OperationStatus GetPendingReports(std::vector* pending_reports) { return pending_reports.size(); } -- (int)pendingReportException { - std::vector pending_reports; - OperationStatus status = GetPendingReports(&pending_reports); - if (status != crashpad::CrashReportDatabase::kNoError || - pending_reports.size() != 1) { - return -1; - } +- (bool)pendingReportException:(NSNumber**)exception { + auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending(); + if (!process_snapshot || !process_snapshot->Exception()->Exception()) + return false; + *exception = [NSNumber + numberWithUnsignedInt:process_snapshot->Exception()->Exception()]; + return true; +} - auto reader = std::make_unique(); - reader->Open(pending_reports[0].file_path); - crashpad::ProcessSnapshotMinidump process_snapshot; - process_snapshot.Initialize(reader.get()); - return static_cast(process_snapshot.Exception()->Exception()); +- (bool)pendingReportExceptionInfo:(NSNumber**)exception_info { + auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending(); + if (!process_snapshot || !process_snapshot->Exception()->ExceptionInfo()) + return false; + + *exception_info = [NSNumber + numberWithUnsignedInt:process_snapshot->Exception()->ExceptionInfo()]; + return true; } - (NSDictionary*)getAnnotations { - std::vector pending_reports; - OperationStatus status = GetPendingReports(&pending_reports); - if (status != crashpad::CrashReportDatabase::kNoError || - pending_reports.size() != 1) { + auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending(); + if (!process_snapshot) return @{}; - } - - auto reader = std::make_unique(); - reader->Open(pending_reports[0].file_path); - crashpad::ProcessSnapshotMinidump process_snapshot; - process_snapshot.Initialize(reader.get()); NSDictionary* dict = @{ @"simplemap" : [@{} mutableCopy], @"vector" : [@[] mutableCopy], @"objects" : [@[] mutableCopy] }; - for (const auto* module : process_snapshot.Modules()) { + for (const auto* module : process_snapshot->Modules()) { for (const auto& kv : module->AnnotationsSimpleMap()) { [dict[@"simplemap"] setValue:@(kv.second.c_str()) forKey:@(kv.first.c_str())]; @@ -215,19 +229,12 @@ OperationStatus GetPendingReports(std::vector* pending_reports) { } - (NSDictionary*)getProcessAnnotations { - std::vector pending_reports; - OperationStatus status = GetPendingReports(&pending_reports); - if (status != crashpad::CrashReportDatabase::kNoError || - pending_reports.size() != 1) { + auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending(); + if (!process_snapshot) return @{}; - } - auto reader = std::make_unique(); - reader->Open(pending_reports[0].file_path); - crashpad::ProcessSnapshotMinidump process_snapshot; - process_snapshot.Initialize(reader.get()); NSDictionary* dict = [@{} mutableCopy]; - for (const auto& kv : process_snapshot.AnnotationsSimpleMap()) { + for (const auto& kv : process_snapshot->AnnotationsSimpleMap()) { [dict setValue:@(kv.second.c_str()) forKey:@(kv.first.c_str())]; } diff --git a/test/ios/host/cptest_shared_object.h b/test/ios/host/cptest_shared_object.h index bcd75547..90e3de8d 100644 --- a/test/ios/host/cptest_shared_object.h +++ b/test/ios/host/cptest_shared_object.h @@ -32,9 +32,15 @@ // report. - (int)pendingReportCount; -// Returns exception code when there's a single pending report, or -1 if there's -// a different number of pending reports. -- (int)pendingReportException; +// Returns true if there's a single pending report and sets the exception code +// in the out |exception| parameter. Returns false if there's a different number +// of pending reports. +- (bool)pendingReportException:(NSNumber**)exception; + +// Returns true if there's a single pending report and sets the second-level +// exception code in the out |exception_info| parameter. Returns false if +// there's a different number of pending reports. +- (bool)pendingReportExceptionInfo:(NSNumber**)exception_info; // Return an NSDictionary with a dictionary named "simplemap", an array named // "vector" and an array named "objects", representing the combination of all