CrashReporter.mm
3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#import "PLCrashReporter.h"
#import "CrashReporter.h"
#include "UndefinePlatforms.h"
#include <mach-o/ldsyms.h>
#include "RedefinePlatforms.h"
extern "C" NSString* UnityGetCrashReportsPath();
static NSUncaughtExceptionHandler* gsCrashReporterUEHandler = NULL;
static decltype(_mh_execute_header) * sExecuteHeader = NULL;
extern "C" void UnitySetExecuteMachHeader(const decltype(_mh_execute_header)* header)
{
sExecuteHeader = header;
}
extern "C" const decltype(_mh_execute_header) * UnityGetExecuteMachHeader() {
return sExecuteHeader;
}
static void SavePendingCrashReport()
{
if (![[UnityPLCrashReporter sharedReporter] hasPendingCrashReport])
return;
NSFileManager *fm = [NSFileManager defaultManager];
NSError *error;
if (![fm createDirectoryAtPath: UnityGetCrashReportsPath() withIntermediateDirectories: YES attributes: nil error: &error])
{
::printf("CrashReporter: could not create crash report directory: %s\n", [[error localizedDescription] UTF8String]);
return;
}
NSData *data = [[UnityPLCrashReporter sharedReporter] loadPendingCrashReportDataAndReturnError: &error];
if (data == nil)
{
::printf("CrashReporter: failed to load crash report data: %s\n", [[error localizedDescription] UTF8String]);
return;
}
NSString* file = [UnityGetCrashReportsPath() stringByAppendingPathComponent: @"crash-"];
unsigned long long seconds = (unsigned long long)[[NSDate date] timeIntervalSince1970];
file = [file stringByAppendingString: [NSString stringWithFormat: @"%llu", seconds]];
file = [file stringByAppendingString: @".plcrash"];
if ([data writeToFile: file atomically: YES])
{
::printf("CrashReporter: saved pending crash report.\n");
if (![[UnityPLCrashReporter sharedReporter] purgePendingCrashReportAndReturnError: &error])
{
::printf("CrashReporter: couldn't remove pending report: %s\n", [[error localizedDescription] UTF8String]);
}
}
else
{
::printf("CrashReporter: couldn't save crash report.\n");
}
// Now copy out a pending version that we can delete if/when we send it
file = [UnityGetCrashReportsPath() stringByAppendingPathComponent: @"crash-pending.plcrash"];
if ([data writeToFile: file atomically: YES])
{
::printf("CrashReporter: saved copy of pending crash report.\n");
}
else
{
::printf("CrashReporter: couldn't save copy of pending crash report.\n");
}
}
static void InitCrashReporter()
{
NSError *error;
UnityInstallPostCrashCallback();
if ([[UnityPLCrashReporter sharedReporter] enableCrashReporterAndReturnError: &error])
::printf("CrashReporter: initialized\n");
else
NSLog(@"CrashReporter: could not enable crash reporter: %@", error);
SavePendingCrashReport();
}
static void UncaughtExceptionHandler(NSException *exception)
{
NSLog(@"Uncaught exception: %@: %@\n%@", [exception name], [exception reason], [exception callStackSymbols]);
if (gsCrashReporterUEHandler)
gsCrashReporterUEHandler(exception);
}
static void InitObjCUEHandler()
{
// Crash reporter sets its own handler, so we have to save it and call it manually
gsCrashReporterUEHandler = NSGetUncaughtExceptionHandler();
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
}
void InitCrashHandling()
{
#if ENABLE_CUSTOM_CRASH_REPORTER
InitCrashReporter();
#endif
#if ENABLE_OBJC_UNCAUGHT_EXCEPTION_HANDLER
InitObjCUEHandler();
#endif
}
// This function will be called when AppDomain.CurrentDomain.UnhandledException event is triggered.
// When running on device the app will do a hard crash and it will generate a crash log.
extern "C" void CrashedCheckBelowForHintsWhy()
{
#if ENABLE_IOS_CRASH_REPORTING || ENABLE_CUSTOM_CRASH_REPORTER
// Make app crash hard here
__builtin_trap();
// Just in case above doesn't work
abort();
#endif
}