ios: Set EXC_SOFT_SIGNAL for signal exceptions.

Right now there's no clear way to differentiate between Signal and Mach
exceptions. Instead, set EXC_SOFT_SIGNAL as the top level exception for
signal exceptions, moving the signal number to ExceptionInfo() and
and the signal code plus the two previous values into Codes().

Fixed:crashpad:389
Change-Id: Ia57f402b98be2a648febb58b9dee0cb80d9e5954
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3388874
Reviewed-by: Mark Mentovai <mark@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
Justin Cohen 2022-01-14 22:25:59 -05:00 committed by Crashpad LUCI CQ
parent 824ddb2de1
commit 243e1fd8e2
4 changed files with 106 additions and 57 deletions

View File

@ -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;
}

View File

@ -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<NSString*>* 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:@""]);

View File

@ -68,6 +68,24 @@ OperationStatus GetPendingReports(std::vector<Report>* pending_reports) {
return database->GetPendingReports(pending_reports);
}
std::unique_ptr<crashpad::ProcessSnapshotMinidump>
GetProcessSnapshotMinidumpFromSinglePending() {
std::vector<Report> pending_reports;
OperationStatus status = GetPendingReports(&pending_reports);
if (status != crashpad::CrashReportDatabase::kNoError ||
pending_reports.size() != 1) {
return nullptr;
}
auto reader = std::make_unique<crashpad::FileReader>();
auto process_snapshot = std::make_unique<crashpad::ProcessSnapshotMinidump>();
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<Report>* pending_reports) {
return pending_reports.size();
}
- (int)pendingReportException {
std::vector<Report> 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<crashpad::FileReader>();
reader->Open(pending_reports[0].file_path);
crashpad::ProcessSnapshotMinidump process_snapshot;
process_snapshot.Initialize(reader.get());
return static_cast<int>(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<Report> 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<crashpad::FileReader>();
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<Report>* pending_reports) {
}
- (NSDictionary*)getProcessAnnotations {
std::vector<Report> 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<crashpad::FileReader>();
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())];
}

View File

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