2022-09-06 19:14:07 -04:00
|
|
|
// Copyright 2020 The Crashpad Authors
|
2020-01-30 22:11:26 -05:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2020-04-15 10:33:31 -04:00
|
|
|
#import "test/ios/host/cptest_application_delegate.h"
|
2020-04-08 15:37:55 -04:00
|
|
|
#include <dispatch/dispatch.h>
|
2021-10-28 17:02:27 -04:00
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <mach-o/dyld.h>
|
|
|
|
#include <mach-o/dyld_images.h>
|
|
|
|
#include <mach-o/nlist.h>
|
2022-03-24 19:43:01 -04:00
|
|
|
#include <objc/objc-exception.h>
|
2020-04-15 10:33:31 -04:00
|
|
|
#include <signal.h>
|
2022-03-08 18:20:41 -05:00
|
|
|
#include <stdio.h>
|
2020-04-15 10:33:31 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2020-04-08 15:37:55 -04:00
|
|
|
|
2022-03-24 19:43:01 -04:00
|
|
|
#include <thread>
|
2020-04-08 15:37:55 -04:00
|
|
|
#include <vector>
|
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
#import "Service/Sources/EDOHostNamingService.h"
|
|
|
|
#import "Service/Sources/EDOHostService.h"
|
2021-10-28 17:02:27 -04:00
|
|
|
#import "Service/Sources/NSObject+EDOValueObject.h"
|
2022-03-08 18:20:41 -05:00
|
|
|
#include "base/logging.h"
|
2021-10-28 17:02:27 -04:00
|
|
|
#include "base/strings/sys_string_conversions.h"
|
|
|
|
#include "client/annotation.h"
|
|
|
|
#include "client/annotation_list.h"
|
|
|
|
#include "client/crash_report_database.h"
|
2020-02-18 14:49:10 -05:00
|
|
|
#include "client/crashpad_client.h"
|
2021-10-28 17:02:27 -04:00
|
|
|
#include "client/crashpad_info.h"
|
|
|
|
#include "client/simple_string_dictionary.h"
|
2022-03-08 18:20:41 -05:00
|
|
|
#include "client/simulate_crash.h"
|
2021-10-28 17:02:27 -04:00
|
|
|
#include "snapshot/minidump/process_snapshot_minidump.h"
|
2022-03-08 18:20:41 -05:00
|
|
|
#include "test/file.h"
|
2020-04-15 10:33:31 -04:00
|
|
|
#import "test/ios/host/cptest_crash_view_controller.h"
|
2020-02-18 14:49:10 -05:00
|
|
|
#import "test/ios/host/cptest_shared_object.h"
|
2022-03-08 20:09:09 -05:00
|
|
|
#import "test/ios/host/handler_forbidden_allocators.h"
|
2022-03-08 18:20:41 -05:00
|
|
|
#include "util/file/filesystem.h"
|
2022-03-15 12:57:26 -04:00
|
|
|
#include "util/ios/raw_logging.h"
|
2022-03-08 18:20:41 -05:00
|
|
|
#include "util/thread/thread.h"
|
2020-01-30 22:11:26 -05:00
|
|
|
|
|
|
|
#if !defined(__has_feature) || !__has_feature(objc_arc)
|
|
|
|
#error "This file requires ARC support."
|
|
|
|
#endif
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
using OperationStatus = crashpad::CrashReportDatabase::OperationStatus;
|
|
|
|
using Report = crashpad::CrashReportDatabase::Report;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
base::FilePath GetDatabaseDir() {
|
|
|
|
base::FilePath database_dir([NSFileManager.defaultManager
|
|
|
|
URLsForDirectory:NSDocumentDirectory
|
|
|
|
inDomains:NSUserDomainMask]
|
|
|
|
.lastObject.path.UTF8String);
|
|
|
|
return database_dir.Append("crashpad");
|
|
|
|
}
|
|
|
|
|
2022-03-15 12:57:26 -04:00
|
|
|
base::FilePath GetRawLogOutputFile() {
|
|
|
|
base::FilePath document_directory([NSFileManager.defaultManager
|
|
|
|
URLsForDirectory:NSDocumentDirectory
|
|
|
|
inDomains:NSUserDomainMask]
|
|
|
|
.lastObject.path.UTF8String);
|
|
|
|
return document_directory.Append("raw_log_output.txt");
|
2022-03-08 18:20:41 -05:00
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
std::unique_ptr<crashpad::CrashReportDatabase> GetDatabase() {
|
|
|
|
base::FilePath database_dir = GetDatabaseDir();
|
|
|
|
std::unique_ptr<crashpad::CrashReportDatabase> database =
|
|
|
|
crashpad::CrashReportDatabase::Initialize(database_dir);
|
|
|
|
return database;
|
|
|
|
}
|
|
|
|
|
|
|
|
OperationStatus GetPendingReports(std::vector<Report>* pending_reports) {
|
|
|
|
std::unique_ptr<crashpad::CrashReportDatabase> database(GetDatabase());
|
|
|
|
return database->GetPendingReports(pending_reports);
|
|
|
|
}
|
|
|
|
|
2022-01-14 22:25:59 -05:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-03-31 13:50:10 -04:00
|
|
|
UIWindow* GetAnyWindow() {
|
|
|
|
#if defined(__IPHONE_15_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_15_0
|
|
|
|
if (@available(iOS 15.0, *)) {
|
|
|
|
UIWindowScene* scene = reinterpret_cast<UIWindowScene*>(
|
|
|
|
[UIApplication sharedApplication].connectedScenes.anyObject);
|
|
|
|
return scene.keyWindow;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return [UIApplication sharedApplication].windows[0];
|
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
[[clang::optnone]] void recurse(int counter) {
|
|
|
|
// Fill up the stack faster.
|
|
|
|
int arr[1024];
|
|
|
|
arr[0] = counter;
|
|
|
|
if (counter > INT_MAX)
|
|
|
|
return;
|
|
|
|
recurse(++counter);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
@interface CPTestApplicationDelegate ()
|
|
|
|
- (void)processIntermediateDumps;
|
2022-03-15 12:57:26 -04:00
|
|
|
@property(copy, nonatomic) NSString* raw_log_output;
|
2021-10-28 17:02:27 -04:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation CPTestApplicationDelegate {
|
|
|
|
crashpad::CrashpadClient client_;
|
2022-03-15 12:57:26 -04:00
|
|
|
crashpad::ScopedFileHandle raw_logging_file_;
|
2021-10-28 17:02:27 -04:00
|
|
|
}
|
2020-04-15 10:33:31 -04:00
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
@synthesize window = _window;
|
|
|
|
|
|
|
|
- (BOOL)application:(UIApplication*)application
|
|
|
|
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
|
2022-03-15 12:57:26 -04:00
|
|
|
base::FilePath raw_log_file_path = GetRawLogOutputFile();
|
|
|
|
NSString* path =
|
|
|
|
[NSString stringWithUTF8String:raw_log_file_path.value().c_str()];
|
|
|
|
self.raw_log_output =
|
|
|
|
[[NSString alloc] initWithContentsOfFile:path
|
|
|
|
encoding:NSUTF8StringEncoding
|
|
|
|
error:NULL];
|
|
|
|
raw_logging_file_.reset(
|
|
|
|
LoggingOpenFileForWrite(raw_log_file_path,
|
|
|
|
crashpad::FileWriteMode::kTruncateOrCreate,
|
|
|
|
crashpad::FilePermissions::kOwnerOnly));
|
|
|
|
crashpad::internal::SetFileHandleForTesting(raw_logging_file_.get());
|
|
|
|
|
2020-02-18 14:49:10 -05:00
|
|
|
// Start up crashpad.
|
2021-11-10 13:04:10 -05:00
|
|
|
std::map<std::string, std::string> annotations = {
|
|
|
|
{"prod", "xcuitest"}, {"ver", "1"}, {"plat", "iOS"}, {"crashpad", "yes"}};
|
|
|
|
NSArray<NSString*>* arguments = [[NSProcessInfo processInfo] arguments];
|
|
|
|
if ([arguments containsObject:@"--alternate-client-annotations"]) {
|
|
|
|
annotations = {{"prod", "some_app"},
|
|
|
|
{"ver", "42"},
|
|
|
|
{"plat", "macOS"},
|
|
|
|
{"crashpad", "no"}};
|
|
|
|
}
|
|
|
|
if (client_.StartCrashpadInProcessHandler(
|
2022-09-09 15:25:08 -06:00
|
|
|
GetDatabaseDir(),
|
|
|
|
"",
|
|
|
|
annotations,
|
|
|
|
crashpad::CrashpadClient::
|
|
|
|
ProcessPendingReportsObservationCallback())) {
|
2021-10-28 17:02:27 -04:00
|
|
|
client_.ProcessIntermediateDumps();
|
|
|
|
}
|
2020-02-18 14:49:10 -05:00
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
|
|
|
[self.window makeKeyAndVisible];
|
|
|
|
self.window.backgroundColor = UIColor.greenColor;
|
|
|
|
|
2020-04-15 10:33:31 -04:00
|
|
|
CPTestCrashViewController* controller =
|
|
|
|
[[CPTestCrashViewController alloc] init];
|
2020-01-30 22:11:26 -05:00
|
|
|
self.window.rootViewController = controller;
|
|
|
|
|
|
|
|
// Start up EDO.
|
|
|
|
[EDOHostService serviceWithPort:12345
|
2020-02-18 14:49:10 -05:00
|
|
|
rootObject:[[CPTestSharedObject alloc] init]
|
2020-01-30 22:11:26 -05:00
|
|
|
queue:dispatch_get_main_queue()];
|
2021-10-28 17:02:27 -04:00
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
- (void)processIntermediateDumps {
|
|
|
|
client_.ProcessIntermediateDumps();
|
|
|
|
}
|
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
@end
|
|
|
|
|
2020-02-18 14:49:10 -05:00
|
|
|
@implementation CPTestSharedObject
|
2020-04-15 10:33:31 -04:00
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
- (NSString*)testEDO {
|
|
|
|
return @"crashpad";
|
|
|
|
}
|
2020-02-18 14:49:10 -05:00
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
- (void)processIntermediateDumps {
|
|
|
|
CPTestApplicationDelegate* delegate =
|
|
|
|
(CPTestApplicationDelegate*)UIApplication.sharedApplication.delegate;
|
|
|
|
[delegate processIntermediateDumps];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)clearPendingReports {
|
|
|
|
std::unique_ptr<crashpad::CrashReportDatabase> database(GetDatabase());
|
|
|
|
std::vector<crashpad::CrashReportDatabase::Report> pending_reports;
|
|
|
|
database->GetPendingReports(&pending_reports);
|
|
|
|
for (auto report : pending_reports) {
|
|
|
|
database->DeleteReport(report.uuid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int)pendingReportCount {
|
|
|
|
std::vector<Report> pending_reports;
|
|
|
|
OperationStatus status = GetPendingReports(&pending_reports);
|
|
|
|
if (status != crashpad::CrashReportDatabase::kNoError) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return pending_reports.size();
|
|
|
|
}
|
|
|
|
|
2022-01-14 22:25:59 -05:00
|
|
|
- (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;
|
|
|
|
}
|
2021-10-28 17:02:27 -04:00
|
|
|
|
2022-01-14 22:25:59 -05:00
|
|
|
- (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;
|
2021-10-28 17:02:27 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSDictionary*)getAnnotations {
|
2022-01-14 22:25:59 -05:00
|
|
|
auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending();
|
|
|
|
if (!process_snapshot)
|
2021-10-28 17:02:27 -04:00
|
|
|
return @{};
|
|
|
|
|
|
|
|
NSDictionary* dict = @{
|
|
|
|
@"simplemap" : [@{} mutableCopy],
|
|
|
|
@"vector" : [@[] mutableCopy],
|
|
|
|
@"objects" : [@[] mutableCopy]
|
|
|
|
};
|
2022-01-14 22:25:59 -05:00
|
|
|
for (const auto* module : process_snapshot->Modules()) {
|
2021-10-28 17:02:27 -04:00
|
|
|
for (const auto& kv : module->AnnotationsSimpleMap()) {
|
|
|
|
[dict[@"simplemap"] setValue:@(kv.second.c_str())
|
|
|
|
forKey:@(kv.first.c_str())];
|
|
|
|
}
|
|
|
|
for (const std::string& annotation : module->AnnotationsVector()) {
|
|
|
|
[dict[@"vector"] addObject:@(annotation.c_str())];
|
|
|
|
}
|
|
|
|
for (const auto& annotation : module->AnnotationObjects()) {
|
|
|
|
if (annotation.type !=
|
|
|
|
static_cast<uint16_t>(crashpad::Annotation::Type::kString)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
std::string value(reinterpret_cast<const char*>(annotation.value.data()),
|
|
|
|
annotation.value.size());
|
|
|
|
[dict[@"objects"]
|
|
|
|
addObject:@{@(annotation.name.c_str()) : @(value.c_str())}];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [dict passByValue];
|
|
|
|
}
|
|
|
|
|
2021-11-10 13:04:10 -05:00
|
|
|
- (NSDictionary*)getProcessAnnotations {
|
2022-01-14 22:25:59 -05:00
|
|
|
auto process_snapshot = GetProcessSnapshotMinidumpFromSinglePending();
|
|
|
|
if (!process_snapshot)
|
2021-11-10 13:04:10 -05:00
|
|
|
return @{};
|
|
|
|
|
|
|
|
NSDictionary* dict = [@{} mutableCopy];
|
2022-01-14 22:25:59 -05:00
|
|
|
for (const auto& kv : process_snapshot->AnnotationsSimpleMap()) {
|
2021-11-10 13:04:10 -05:00
|
|
|
[dict setValue:@(kv.second.c_str()) forKey:@(kv.first.c_str())];
|
|
|
|
}
|
|
|
|
|
|
|
|
return [dict passByValue];
|
|
|
|
}
|
|
|
|
|
2022-01-20 12:16:41 -05:00
|
|
|
// Use [[clang::optnone]] here to get consistent exception codes, otherwise the
|
|
|
|
// exception can change depending on optimization level.
|
|
|
|
- (void)crashBadAccess [[clang::optnone]] {
|
2020-04-15 10:33:31 -04:00
|
|
|
strcpy(nullptr, "bla");
|
2020-02-18 14:49:10 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)crashKillAbort {
|
2022-03-08 20:09:09 -05:00
|
|
|
crashpad::test::ReplaceAllocatorsWithHandlerForbidden();
|
2020-02-18 14:49:10 -05:00
|
|
|
kill(getpid(), SIGABRT);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)crashTrap {
|
2022-03-08 20:09:09 -05:00
|
|
|
crashpad::test::ReplaceAllocatorsWithHandlerForbidden();
|
2020-02-18 14:49:10 -05:00
|
|
|
__builtin_trap();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)crashAbort {
|
2022-03-08 20:09:09 -05:00
|
|
|
crashpad::test::ReplaceAllocatorsWithHandlerForbidden();
|
2020-02-18 14:49:10 -05:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
2020-04-08 15:37:55 -04:00
|
|
|
- (void)crashException {
|
|
|
|
std::vector<int> empty_vector = {};
|
|
|
|
empty_vector.at(42);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)crashNSException {
|
2022-03-08 18:20:41 -05:00
|
|
|
// EDO has its own sinkhole which will suppress this attempt at an NSException
|
|
|
|
// crash, so dispatch this out of the sinkhole.
|
2020-04-08 15:37:55 -04:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
2021-10-28 17:02:27 -04:00
|
|
|
NSError* error = [NSError errorWithDomain:@"com.crashpad.xcuitests"
|
|
|
|
code:200
|
|
|
|
userInfo:@{@"Error Object" : self}];
|
|
|
|
|
|
|
|
[[NSException exceptionWithName:NSInternalInconsistencyException
|
|
|
|
reason:@"Intentionally throwing error."
|
|
|
|
userInfo:@{NSUnderlyingErrorKey : error}] raise];
|
2020-04-08 15:37:55 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-03-24 19:43:01 -04:00
|
|
|
- (void)crashUnhandledNSException {
|
|
|
|
std::thread t([self]() {
|
|
|
|
@autoreleasepool {
|
|
|
|
@try {
|
|
|
|
NSError* error = [NSError errorWithDomain:@"com.crashpad.xcuitests"
|
|
|
|
code:200
|
|
|
|
userInfo:@{@"Error Object" : self}];
|
|
|
|
|
|
|
|
[[NSException exceptionWithName:NSInternalInconsistencyException
|
|
|
|
reason:@"Intentionally throwing error."
|
|
|
|
userInfo:@{NSUnderlyingErrorKey : error}] raise];
|
|
|
|
} @catch (id reason_exception) {
|
|
|
|
// Intentionally use throw here to intentionally make a sinkhole that
|
|
|
|
// will be missed by ObjcPreprocessor.
|
|
|
|
objc_exception_throw(reason_exception);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
t.join();
|
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
- (void)crashUnrecognizedSelectorAfterDelay {
|
|
|
|
#pragma clang diagnostic push
|
|
|
|
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
|
|
|
[self performSelector:@selector(does_not_exist) withObject:nil afterDelay:1];
|
|
|
|
#pragma clang diagnostic pop
|
|
|
|
}
|
|
|
|
|
2020-04-08 15:37:55 -04:00
|
|
|
- (void)catchNSException {
|
|
|
|
@try {
|
|
|
|
NSArray* empty_array = @[];
|
|
|
|
[empty_array objectAtIndex:42];
|
|
|
|
} @catch (NSException* exception) {
|
|
|
|
} @finally {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-05 14:34:13 -04:00
|
|
|
- (void)crashCoreAutoLayoutSinkhole {
|
2022-03-08 18:20:41 -05:00
|
|
|
// EDO has its own sinkhole which will suppress this attempt at an NSException
|
|
|
|
// crash, so dispatch this out of the sinkhole.
|
2021-11-05 14:34:13 -04:00
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
UIView* unattachedView = [[UIView alloc] init];
|
2022-03-31 13:50:10 -04:00
|
|
|
UIWindow* window = GetAnyWindow();
|
2021-11-05 14:34:13 -04:00
|
|
|
[NSLayoutConstraint activateConstraints:@[
|
|
|
|
[window.rootViewController.view.bottomAnchor
|
|
|
|
constraintEqualToAnchor:unattachedView.bottomAnchor],
|
|
|
|
]];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
- (void)crashRecursion {
|
|
|
|
recurse(0);
|
2020-04-08 15:37:55 -04:00
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
- (void)crashWithCrashInfoMessage {
|
|
|
|
dlsym(nullptr, nullptr);
|
2020-04-08 15:37:55 -04:00
|
|
|
}
|
|
|
|
|
2021-10-28 17:02:27 -04:00
|
|
|
- (void)crashWithDyldErrorString {
|
|
|
|
std::string crashy_initializer =
|
|
|
|
base::SysNSStringToUTF8([[NSBundle mainBundle]
|
|
|
|
pathForResource:@"crashpad_snapshot_test_module_crashy_initializer"
|
|
|
|
ofType:@"so"]);
|
|
|
|
dlopen(crashy_initializer.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)crashWithAnnotations {
|
|
|
|
// This is “leaked” to crashpad_info.
|
|
|
|
crashpad::SimpleStringDictionary* simple_annotations =
|
|
|
|
new crashpad::SimpleStringDictionary();
|
|
|
|
simple_annotations->SetKeyValue("#TEST# pad", "break");
|
|
|
|
simple_annotations->SetKeyValue("#TEST# key", "value");
|
|
|
|
simple_annotations->SetKeyValue("#TEST# pad", "crash");
|
|
|
|
simple_annotations->SetKeyValue("#TEST# x", "y");
|
|
|
|
simple_annotations->SetKeyValue("#TEST# longer", "shorter");
|
|
|
|
simple_annotations->SetKeyValue("#TEST# empty_value", "");
|
|
|
|
|
|
|
|
crashpad::CrashpadInfo* crashpad_info =
|
|
|
|
crashpad::CrashpadInfo::GetCrashpadInfo();
|
|
|
|
|
|
|
|
crashpad_info->set_simple_annotations(simple_annotations);
|
|
|
|
|
|
|
|
crashpad::AnnotationList::Register(); // This is “leaked” to crashpad_info.
|
|
|
|
|
|
|
|
static crashpad::StringAnnotation<32> test_annotation_one{"#TEST# one"};
|
|
|
|
static crashpad::StringAnnotation<32> test_annotation_two{"#TEST# two"};
|
|
|
|
static crashpad::StringAnnotation<32> test_annotation_three{
|
|
|
|
"#TEST# same-name"};
|
|
|
|
static crashpad::StringAnnotation<32> test_annotation_four{
|
|
|
|
"#TEST# same-name"};
|
|
|
|
|
|
|
|
test_annotation_one.Set("moocow");
|
|
|
|
test_annotation_two.Set("this will be cleared");
|
|
|
|
test_annotation_three.Set("same-name 3");
|
|
|
|
test_annotation_four.Set("same-name 4");
|
|
|
|
test_annotation_two.Clear();
|
|
|
|
abort();
|
2020-04-08 15:37:55 -04:00
|
|
|
}
|
|
|
|
|
2022-03-08 18:20:41 -05:00
|
|
|
class RaceThread : public crashpad::Thread {
|
|
|
|
public:
|
|
|
|
explicit RaceThread() : Thread() {}
|
|
|
|
|
|
|
|
void SetCount(int count) { count_ = count; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
void ThreadMain() override {
|
|
|
|
for (int i = 0; i < count_; ++i) {
|
|
|
|
CRASHPAD_SIMULATE_CRASH();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int count_;
|
|
|
|
};
|
|
|
|
|
|
|
|
- (void)generateDumpWithoutCrash:(int)dump_count threads:(int)threads {
|
|
|
|
std::vector<RaceThread> race_threads(threads);
|
|
|
|
for (RaceThread& race_thread : race_threads) {
|
|
|
|
race_thread.SetCount(dump_count);
|
|
|
|
race_thread.Start();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (RaceThread& race_thread : race_threads) {
|
|
|
|
race_thread.Join();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class CrashThread : public crashpad::Thread {
|
|
|
|
public:
|
|
|
|
explicit CrashThread(bool signal) : Thread(), signal_(signal) {}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void ThreadMain() override {
|
|
|
|
sleep(1);
|
|
|
|
if (signal_) {
|
|
|
|
abort();
|
|
|
|
} else {
|
|
|
|
__builtin_trap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bool signal_;
|
|
|
|
};
|
|
|
|
|
|
|
|
- (void)crashConcurrentSignalAndMach {
|
|
|
|
CrashThread signal_thread(true);
|
|
|
|
CrashThread mach_thread(false);
|
|
|
|
signal_thread.Start();
|
|
|
|
mach_thread.Start();
|
|
|
|
signal_thread.Join();
|
|
|
|
mach_thread.Join();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)crashInHandlerReentrant {
|
|
|
|
crashpad::CrashpadClient client_;
|
|
|
|
client_.SetMachExceptionCallbackForTesting(abort);
|
|
|
|
|
|
|
|
// Trigger a Mach exception.
|
|
|
|
[self crashTrap];
|
|
|
|
}
|
|
|
|
|
2022-03-08 20:09:09 -05:00
|
|
|
- (void)allocateWithForbiddenAllocators {
|
|
|
|
crashpad::test::ReplaceAllocatorsWithHandlerForbidden();
|
|
|
|
(void)malloc(10);
|
|
|
|
}
|
|
|
|
|
2022-03-15 12:57:26 -04:00
|
|
|
- (NSString*)rawLogContents {
|
2022-03-08 20:09:09 -05:00
|
|
|
CPTestApplicationDelegate* delegate =
|
|
|
|
(CPTestApplicationDelegate*)UIApplication.sharedApplication.delegate;
|
2022-03-15 12:57:26 -04:00
|
|
|
return delegate.raw_log_output;
|
2022-03-08 18:20:41 -05:00
|
|
|
}
|
|
|
|
|
2020-01-30 22:11:26 -05:00
|
|
|
@end
|