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