CrashReporter.mm 3.9 KB

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