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
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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:@""]);
|
||||
|
@ -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())];
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user