diff options
Diffstat (limited to 'StoneIsland/platforms/ios/Pods/FirebaseCrashlytics')
212 files changed, 25953 insertions, 0 deletions
diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h new file mode 100644 index 00000000..75536f7c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.h @@ -0,0 +1,88 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#if CLS_TARGET_OS_HAS_UIKIT +#import <UIKit/UIKit.h> +#endif + +__BEGIN_DECLS + +#define FIRCLSApplicationActivityDefault \ + (NSActivitySuddenTerminationDisabled | NSActivityAutomaticTerminationDisabled) + +/** + * Type to indicate application installation source + */ +typedef NS_ENUM(NSInteger, FIRCLSApplicationInstallationSourceType) { + FIRCLSApplicationInstallationSourceTypeDeveloperInstall = 1, + // 2 and 3 are reserved for legacy values. + FIRCLSApplicationInstallationSourceTypeAppStore = 4 +}; + +/** + * Returns the application bundle identifier with occurences of "/" replaced by "_" + */ +NSString* FIRCLSApplicationGetBundleIdentifier(void); + +/** + * Returns the SDK's bundle ID + */ +NSString* FIRCLSApplicationGetSDKBundleID(void); + +/** + * Returns the platform identifier, either: ios, mac, or tvos. + * Catalyst apps are treated as mac. + */ +NSString* FIRCLSApplicationGetPlatform(void); + +/** + * Returns the user-facing app name + */ +NSString* FIRCLSApplicationGetName(void); + +/** + * Returns the build number + */ +NSString* FIRCLSApplicationGetBundleVersion(void); + +/** + * Returns the human-readable build version + */ +NSString* FIRCLSApplicationGetShortBundleVersion(void); + +/** + * Returns a number to indicate how the app has been installed: Developer / App Store + */ +FIRCLSApplicationInstallationSourceType FIRCLSApplicationInstallationSource(void); + +BOOL FIRCLSApplicationIsExtension(void); +NSString* FIRCLSApplicationExtensionPointIdentifier(void); + +#if CLS_TARGET_OS_HAS_UIKIT +UIApplication* FIRCLSApplicationSharedInstance(void); +#else +id FIRCLSApplicationSharedInstance(void); +#endif + +void FIRCLSApplicationOpenURL(NSURL* url, + NSExtensionContext* extensionContext, + void (^completionBlock)(BOOL success)); + +id<NSObject> FIRCLSApplicationBeginActivity(NSActivityOptions options, NSString* reason); +void FIRCLSApplicationEndActivity(id<NSObject> activity); + +void FIRCLSApplicationActivity(NSActivityOptions options, NSString* reason, void (^block)(void)); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m new file mode 100644 index 00000000..40c4c583 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSApplication.m @@ -0,0 +1,211 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSHost.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#if CLS_TARGET_OS_OSX +#import <AppKit/AppKit.h> +#endif + +#if CLS_TARGET_OS_HAS_UIKIT +#import <UIKit/UIKit.h> +#endif + +NSString* FIRCLSApplicationGetBundleIdentifier(void) { + return [[[NSBundle mainBundle] bundleIdentifier] stringByReplacingOccurrencesOfString:@"/" + withString:@"_"]; +} + +NSString* FIRCLSApplicationGetSDKBundleID(void) { + return + [@"com.google.firebase.crashlytics." stringByAppendingString:FIRCLSApplicationGetPlatform()]; +} + +NSString* FIRCLSApplicationGetPlatform(void) { +#if defined(TARGET_OS_MACCATALYST) && TARGET_OS_MACCATALYST + return @"mac"; +#elif TARGET_OS_IOS + return @"ios"; +#elif TARGET_OS_OSX + return @"mac"; +#elif TARGET_OS_TV + return @"tvos"; +#endif +} + +// these defaults match the FIRCLSInfoPlist helper in FIRCLSIDEFoundation +NSString* FIRCLSApplicationGetBundleVersion(void) { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; +} + +NSString* FIRCLSApplicationGetShortBundleVersion(void) { + return [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; +} + +NSString* FIRCLSApplicationGetName(void) { + NSString* name; + NSBundle* mainBundle; + + mainBundle = [NSBundle mainBundle]; + + name = [mainBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + if (name) { + return name; + } + + name = [mainBundle objectForInfoDictionaryKey:@"CFBundleName"]; + if (name) { + return name; + } + + return FIRCLSApplicationGetBundleVersion(); +} + +BOOL FIRCLSApplicationHasAppStoreReceipt(void) { + NSURL* url = NSBundle.mainBundle.appStoreReceiptURL; + return [NSFileManager.defaultManager fileExistsAtPath:[url path]]; +} + +FIRCLSApplicationInstallationSourceType FIRCLSApplicationInstallationSource(void) { + if (FIRCLSApplicationHasAppStoreReceipt()) { + return FIRCLSApplicationInstallationSourceTypeAppStore; + } + + return FIRCLSApplicationInstallationSourceTypeDeveloperInstall; +} + +BOOL FIRCLSApplicationIsExtension(void) { + return FIRCLSApplicationExtensionPointIdentifier() != nil; +} + +NSString* FIRCLSApplicationExtensionPointIdentifier(void) { + id extensionDict = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"NSExtension"]; + + if (!extensionDict) { + return nil; + } + + if (![extensionDict isKindOfClass:[NSDictionary class]]) { + FIRCLSSDKLog("Error: NSExtension Info.plist entry is mal-formed\n"); + return nil; + } + + id typeValue = [(NSDictionary*)extensionDict objectForKey:@"NSExtensionPointIdentifier"]; + + if (![typeValue isKindOfClass:[NSString class]]) { + FIRCLSSDKLog("Error: NSExtensionPointIdentifier Info.plist entry is mal-formed\n"); + return nil; + } + + return typeValue; +} + +#if CLS_TARGET_OS_HAS_UIKIT +UIApplication* FIRCLSApplicationSharedInstance(void) { + if (FIRCLSApplicationIsExtension()) { + return nil; + } + + return [[UIApplication class] performSelector:@selector(sharedApplication)]; +} +#elif CLS_TARGET_OS_OSX +id FIRCLSApplicationSharedInstance(void) { + return [NSClassFromString(@"NSApplication") sharedApplication]; +} +#else +id FIRCLSApplicationSharedInstance(void) { + return nil; // FIXME: what do we actually return for watch? +} +#endif + +void FIRCLSApplicationOpenURL(NSURL* url, + NSExtensionContext* extensionContext, + void (^completionBlock)(BOOL success)) { + if (extensionContext) { + [extensionContext openURL:url completionHandler:completionBlock]; + return; + } + + BOOL result = NO; + +#if TARGET_OS_IOS + // What's going on here is the value returned is a scalar, but we really need an object to + // call this dynamically. Hoops must be jumped. + NSInvocationOperation* op = + [[NSInvocationOperation alloc] initWithTarget:FIRCLSApplicationSharedInstance() + selector:@selector(openURL:) + object:url]; + [op start]; + [op.result getValue:&result]; +#elif CLS_TARGET_OS_OSX + result = [[NSClassFromString(@"NSWorkspace") sharedWorkspace] openURL:url]; +#endif + + completionBlock(result); +} + +id<NSObject> FIRCLSApplicationBeginActivity(NSActivityOptions options, NSString* reason) { + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions: + reason:)]) { + return [[NSProcessInfo processInfo] beginActivityWithOptions:options reason:reason]; + } + +#if CLS_TARGET_OS_OSX + if (options & NSActivitySuddenTerminationDisabled) { + [[NSProcessInfo processInfo] disableSuddenTermination]; + } + + if (options & NSActivityAutomaticTerminationDisabled) { + [[NSProcessInfo processInfo] disableAutomaticTermination:reason]; + } +#endif + + // encode the options, so we can undo our work later + return @{@"options" : @(options), @"reason" : reason}; +} + +void FIRCLSApplicationEndActivity(id<NSObject> activity) { + if (!activity) { + return; + } + + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(endActivity:)]) { + [[NSProcessInfo processInfo] endActivity:activity]; + return; + } + +#if CLS_TARGET_OS_OSX + NSInteger options = [[(NSDictionary*)activity objectForKey:@"options"] integerValue]; + + if (options & NSActivitySuddenTerminationDisabled) { + [[NSProcessInfo processInfo] enableSuddenTermination]; + } + + if (options & NSActivityAutomaticTerminationDisabled) { + [[NSProcessInfo processInfo] + enableAutomaticTermination:[(NSDictionary*)activity objectForKey:@"reason"]]; + } +#endif +} + +void FIRCLSApplicationActivity(NSActivityOptions options, NSString* reason, void (^block)(void)) { + id<NSObject> activity = FIRCLSApplicationBeginActivity(options, reason); + + block(); + + FIRCLSApplicationEndActivity(activity); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h new file mode 100644 index 00000000..af09ccf9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h @@ -0,0 +1,81 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#include "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" + +__BEGIN_DECLS + +// Typically, apps seem to have ~300 binary images loaded +#define CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT (512) +#define CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE (32) +#define CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME 0 + +#define FIRCLSUUIDStringLength (33) + +typedef struct { + _Atomic(void*) volatile baseAddress; + uint64_t size; +#if CLS_DWARF_UNWINDING_SUPPORTED + const void* ehFrame; +#endif +#if CLS_COMPACT_UNWINDING_SUPPORTED + const void* unwindInfo; +#endif + const void* crashInfo; +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + char name[CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE]; +#endif +} FIRCLSBinaryImageRuntimeNode; + +typedef struct { + char uuidString[FIRCLSUUIDStringLength]; + bool encrypted; + FIRCLSMachOVersion builtSDK; + FIRCLSMachOVersion minSDK; + FIRCLSBinaryImageRuntimeNode node; + struct FIRCLSMachOSlice slice; + intptr_t vmaddr_slide; +} FIRCLSBinaryImageDetails; + +typedef struct { + const char* path; +} FIRCLSBinaryImageReadOnlyContext; + +typedef struct { + FIRCLSFile file; + FIRCLSBinaryImageRuntimeNode nodes[CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT]; +} FIRCLSBinaryImageReadWriteContext; + +void FIRCLSBinaryImageInit(FIRCLSBinaryImageReadOnlyContext* roContext, + FIRCLSBinaryImageReadWriteContext* rwContext); + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSBinaryImageSafeFindImageForAddress(uintptr_t address, + FIRCLSBinaryImageRuntimeNode* image); +bool FIRCLSBinaryImageSafeHasUnwindInfo(FIRCLSBinaryImageRuntimeNode* image); +#endif + +bool FIRCLSBinaryImageFindImageForUUID(const char* uuidString, + FIRCLSBinaryImageDetails* imageDetails); + +bool FIRCLSBinaryImageRecordMainExecutable(FIRCLSFile* file); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m new file mode 100644 index 00000000..7bbf4430 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.m @@ -0,0 +1,571 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h" + +#include <libkern/OSAtomic.h> +#include <mach-o/dyld.h> + +#include <mach-o/getsect.h> + +#include <stdatomic.h> + +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#include "Crashlytics/Shared/FIRCLSByteUtility.h" +#include "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" + +#include <dispatch/dispatch.h> + +// this is defined only if __OPEN_SOURCE__ is *not* defined in the TVOS SDK's mach-o/loader.h +// also, it has not yet made it back to the OSX SDKs, for example +#ifndef LC_VERSION_MIN_TVOS +#define LC_VERSION_MIN_TVOS 0x2F +#endif + +#pragma mark Prototypes +static bool FIRCLSBinaryImageOpenIfNeeded(bool* needsClosing); + +static void FIRCLSBinaryImageAddedCallback(const struct mach_header* mh, intptr_t vmaddr_slide); +static void FIRCLSBinaryImageRemovedCallback(const struct mach_header* mh, intptr_t vmaddr_slide); +static void FIRCLSBinaryImageChanged(bool added, + const struct mach_header* mh, + intptr_t vmaddr_slide); +static bool FIRCLSBinaryImageFillInImageDetails(FIRCLSBinaryImageDetails* details); + +static void FIRCLSBinaryImageStoreNode(bool added, FIRCLSBinaryImageDetails imageDetails); +static void FIRCLSBinaryImageRecordSlice(bool added, const FIRCLSBinaryImageDetails imageDetails); + +#pragma mark - Core API +void FIRCLSBinaryImageInit(FIRCLSBinaryImageReadOnlyContext* roContext, + FIRCLSBinaryImageReadWriteContext* rwContext) { + // initialize our node array to all zeros + memset(&_firclsContext.writable->binaryImage, 0, sizeof(_firclsContext.writable->binaryImage)); + _firclsContext.writable->binaryImage.file.fd = -1; + + dispatch_async(FIRCLSGetBinaryImageQueue(), ^{ + if (!FIRCLSUnlinkIfExists(_firclsContext.readonly->binaryimage.path)) { + FIRCLSSDKLog("Unable to reset the binary image log file %s\n", strerror(errno)); + } + + bool needsClosing; // unneeded + if (!FIRCLSBinaryImageOpenIfNeeded(&needsClosing)) { + FIRCLSSDKLog("Error: Unable to open the binary image log file during init\n"); + } + }); + + _dyld_register_func_for_add_image(FIRCLSBinaryImageAddedCallback); + _dyld_register_func_for_remove_image(FIRCLSBinaryImageRemovedCallback); + + dispatch_async(FIRCLSGetBinaryImageQueue(), ^{ + FIRCLSFileClose(&_firclsContext.writable->binaryImage.file); + }); +} + +static bool FIRCLSBinaryImageOpenIfNeeded(bool* needsClosing) { + if (!FIRCLSIsValidPointer(_firclsContext.writable)) { + return false; + } + + if (!FIRCLSIsValidPointer(_firclsContext.readonly)) { + return false; + } + + if (!FIRCLSIsValidPointer(needsClosing)) { + return false; + } + + *needsClosing = false; + + if (FIRCLSFileIsOpen(&_firclsContext.writable->binaryImage.file)) { + return true; + } + + if (!FIRCLSFileInitWithPath(&_firclsContext.writable->binaryImage.file, + _firclsContext.readonly->binaryimage.path, false)) { + FIRCLSSDKLog("Error: unable to open binary image log file\n"); + return false; + } + + *needsClosing = true; + + return true; +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSBinaryImageSafeFindImageForAddress(uintptr_t address, + FIRCLSBinaryImageRuntimeNode* image) { + if (!FIRCLSContextIsInitialized()) { + return false; + } + + if (address == 0) { + return false; + } + + if (!FIRCLSIsValidPointer(image)) { + return false; + } + + FIRCLSBinaryImageRuntimeNode* nodes = _firclsContext.writable->binaryImage.nodes; + if (!nodes) { + FIRCLSSDKLogError("The node structure is NULL\n"); + return false; + } + + for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) { + FIRCLSBinaryImageRuntimeNode* node = &nodes[i]; + if (!FIRCLSIsValidPointer(node)) { + FIRCLSSDKLog( + "Invalid node pointer encountered in context's writable binary image at index %i", i); + continue; + } + + if ((address >= (uintptr_t)node->baseAddress) && + (address < (uintptr_t)node->baseAddress + node->size)) { + *image = *node; // copy the image + return true; + } + } + + return false; +} + +bool FIRCLSBinaryImageSafeHasUnwindInfo(FIRCLSBinaryImageRuntimeNode* image) { + return FIRCLSIsValidPointer(image->unwindInfo); +} +#endif + +bool FIRCLSBinaryImageFindImageForUUID(const char* uuidString, + FIRCLSBinaryImageDetails* imageDetails) { + if (!imageDetails || !uuidString) { + FIRCLSSDKLog("null input\n"); + return false; + } + + uint32_t imageCount = _dyld_image_count(); + + for (uint32_t i = 0; i < imageCount; ++i) { + const struct mach_header* mh = _dyld_get_image_header(i); + + FIRCLSBinaryImageDetails image; + + image.slice = FIRCLSMachOSliceWithHeader((void*)mh); + FIRCLSBinaryImageFillInImageDetails(&image); + + if (strncmp(uuidString, image.uuidString, FIRCLSUUIDStringLength) == 0) { + *imageDetails = image; + return true; + } + } + + return false; +} + +#pragma mark - DYLD callback handlers +static void FIRCLSBinaryImageAddedCallback(const struct mach_header* mh, intptr_t vmaddr_slide) { + FIRCLSBinaryImageChanged(true, mh, vmaddr_slide); +} + +static void FIRCLSBinaryImageRemovedCallback(const struct mach_header* mh, intptr_t vmaddr_slide) { + FIRCLSBinaryImageChanged(false, mh, vmaddr_slide); +} + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME +static bool FIRCLSBinaryImagePopulateRuntimeNodeName(FIRCLSBinaryImageDetails* details) { + if (!FIRCLSIsValidPointer(details)) { + return false; + } + + memset(details->node.name, 0, CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE); + + // We have limited storage space for the name. And, we really want to store + // "CoreFoundation", not "/System/Library/Fram", so we have to play tricks + // to make sure we get the right side of the string. + const char* imageName = FIRCLSMachOSliceGetExecutablePath(&details->slice); + if (!imageName) { + return false; + } + + const size_t imageNameLength = strlen(imageName); + + // Remember to leave one character for null-termination. + if (imageNameLength > CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1) { + imageName = imageName + (imageNameLength - (CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1)); + } + + // subtract one to make sure the string is always null-terminated + strncpy(details->node.name, imageName, CLS_BINARY_IMAGE_RUNTIME_NODE_NAME_SIZE - 1); + + return true; +} +#endif + +// There were plans later to replace this with FIRCLSMachO +static FIRCLSMachOSegmentCommand FIRCLSBinaryImageMachOGetSegmentCommand( + const struct load_command* cmd) { + FIRCLSMachOSegmentCommand segmentCommand; + + memset(&segmentCommand, 0, sizeof(FIRCLSMachOSegmentCommand)); + + if (!cmd) { + return segmentCommand; + } + + if (cmd->cmd == LC_SEGMENT) { + struct segment_command* segCmd = (struct segment_command*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } else if (cmd->cmd == LC_SEGMENT_64) { + struct segment_command_64* segCmd = (struct segment_command_64*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } + + return segmentCommand; +} + +static bool FIRCLSBinaryImageMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + FIRCLSMachOSection* section) { + if (!FIRCLSIsValidPointer(slice)) { + return false; + } + + if (!section) { + return false; + } + + memset(section, 0, sizeof(FIRCLSMachOSection)); + + if (FIRCLSMachOSliceIs64Bit(slice)) { + const struct section_64* sect = + getsectbynamefromheader_64(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } else { + const struct section* sect = getsectbynamefromheader(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } + + return true; +} + +static bool FIRCLSBinaryImageFillInImageDetails(FIRCLSBinaryImageDetails* details) { + if (!FIRCLSIsValidPointer(details)) { + return false; + } + + if (!FIRCLSIsValidPointer(details->slice.startAddress)) { + return false; + } + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + // this is done for debugging purposes, so if it fails, its ok to continue + FIRCLSBinaryImagePopulateRuntimeNodeName(details); +#endif + + // This cast might look a little dubious, but its just because we're using the same + // struct types in a few different places. + details->node.baseAddress = (void* volatile)details->slice.startAddress; + + FIRCLSMachOSliceEnumerateLoadCommands( + &details->slice, ^(uint32_t type, uint32_t size, const struct load_command* cmd) { + switch (type) { + case LC_UUID: { + const uint8_t* uuid = FIRCLSMachOGetUUID(cmd); + FIRCLSSafeHexToString(uuid, 16, details->uuidString); + } break; + case LC_ENCRYPTION_INFO: + details->encrypted = FIRCLSMachOGetEncrypted(cmd); + break; + case LC_SEGMENT: + case LC_SEGMENT_64: { + FIRCLSMachOSegmentCommand segmentCommand = FIRCLSBinaryImageMachOGetSegmentCommand(cmd); + + if (strncmp(segmentCommand.segname, SEG_TEXT, sizeof(SEG_TEXT)) == 0) { + details->node.size = segmentCommand.vmsize; + } + } break; + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_TVOS: + case LC_VERSION_MIN_WATCHOS: + details->minSDK = FIRCLSMachOGetMinimumOSVersion(cmd); + details->builtSDK = FIRCLSMachOGetLinkedSDKVersion(cmd); + break; + } + }); + + // We look up the section we want, and we *should* be able to use: + // + // address of data we want = start address + section.offset + // + // However, the offset value is coming back funky in iOS 9. So, instead we look up the address + // the section should be loaded at, and compute the offset by looking up the address of the + // segment itself. + + FIRCLSMachOSection section; + +#if CLS_COMPACT_UNWINDING_SUPPORTED + if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_TEXT, "__unwind_info", + §ion)) { + details->node.unwindInfo = (void*)(section.addr + details->vmaddr_slide); + } +#endif + +#if CLS_DWARF_UNWINDING_SUPPORTED + if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_TEXT, "__eh_frame", + §ion)) { + details->node.ehFrame = (void*)(section.addr + details->vmaddr_slide); + } +#endif + + if (FIRCLSBinaryImageMachOSliceInitSectionByName(&details->slice, SEG_DATA, "__crash_info", + §ion)) { + details->node.crashInfo = (void*)(section.addr + details->vmaddr_slide); + } + + return true; +} + +static void FIRCLSBinaryImageChanged(bool added, + const struct mach_header* mh, + intptr_t vmaddr_slide) { + // FIRCLSSDKLog("Binary image %s %p\n", added ? "loaded" : "unloaded", mh); + + FIRCLSBinaryImageDetails imageDetails; + + memset(&imageDetails, 0, sizeof(FIRCLSBinaryImageDetails)); + + imageDetails.slice = FIRCLSMachOSliceWithHeader((void*)mh); + imageDetails.vmaddr_slide = vmaddr_slide; + FIRCLSBinaryImageFillInImageDetails(&imageDetails); + + // this is an atomic operation + FIRCLSBinaryImageStoreNode(added, imageDetails); + + // this isn't, so do it on a serial queue + dispatch_async(FIRCLSGetBinaryImageQueue(), ^{ + FIRCLSBinaryImageRecordSlice(added, imageDetails); + }); +} + +#pragma mark - In-Memory Storage +static void FIRCLSBinaryImageStoreNode(bool added, FIRCLSBinaryImageDetails imageDetails) { + // This function is mutating a structure that needs to be accessed at crash time. We + // need to make sure the structure is always in as valid a state as possible. + // FIRCLSSDKLog("Storing %s node %p\n", added ? "loaded" : "unloaded", + // (void*)imageDetails.node.baseAddress); + + if (!_firclsContext.writable) { + FIRCLSSDKLog("Error: Writable context is NULL\n"); + return; + } + + void* searchAddress = NULL; + bool success = false; + FIRCLSBinaryImageRuntimeNode* nodes = _firclsContext.writable->binaryImage.nodes; + + if (!added) { + // capture the search address first + searchAddress = imageDetails.node.baseAddress; + + // If we are removing a node, we need to set its entries to zero. By clearing all of + // these values, we can just copy in imageDetails.node. Using memset here is slightly + // weird, since we have to restore one field. But, this way, if/when the structure changes, + // we still do the right thing. + memset(&imageDetails.node, 0, sizeof(FIRCLSBinaryImageRuntimeNode)); + + // restore the baseAddress, which just got zeroed, and is used for indexing + imageDetails.node.baseAddress = searchAddress; + } + + for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) { + FIRCLSBinaryImageRuntimeNode* node = &nodes[i]; + + if (!node) { + FIRCLSSDKLog("Error: Binary image storage is NULL\n"); + break; + } + + // navigate through the array, looking for our matching address + if (node->baseAddress != searchAddress) { + continue; + } + + // Attempt to swap the base address with whatever we are searching for. Success means that + // entry has been claims/cleared. Failure means some other thread beat us to it. + if (atomic_compare_exchange_strong(&node->baseAddress, &searchAddress, + imageDetails.node.baseAddress)) { + *node = imageDetails.node; + success = true; + + break; + } + + // If this is an unload, getting here means two threads unloaded at the same time. I think + // that's highly unlikely, and possibly even impossible. So, I'm choosing to abort the process + // at this point. + if (!added) { + FIRCLSSDKLog("Error: Failed to swap during image unload\n"); + break; + } + } + + if (!success) { + FIRCLSSDKLog("Error: Unable to track a %s node %p\n", added ? "loaded" : "unloaded", + (void*)imageDetails.node.baseAddress); + } +} + +#pragma mark - On-Disk Storage +static void FIRCLSBinaryImageRecordDetails(FIRCLSFile* file, + const FIRCLSBinaryImageDetails imageDetails) { + if (!file) { + FIRCLSSDKLog("Error: file is invalid\n"); + return; + } + + FIRCLSFileWriteHashEntryString(file, "uuid", imageDetails.uuidString); + FIRCLSFileWriteHashEntryUint64(file, "base", (uintptr_t)imageDetails.slice.startAddress); + FIRCLSFileWriteHashEntryUint64(file, "size", imageDetails.node.size); +} + +static void FIRCLSBinaryImageRecordLibraryFrameworkInfo(FIRCLSFile* file, const char* path) { + if (!file) { + FIRCLSSDKLog("Error: file is invalid\n"); + return; + } + + if (!path) { + return; + } + + // Because this function is so expensive, we've decided to omit this info for all Apple-supplied + // frameworks. This really isn't that bad, because we can know their info ahead of time (within a + // small margin of error). With this implemenation, we will still record this info for any + // user-built framework, which in the end is the most important thing. + if (strncmp(path, "/System", 7) == 0) { + return; + } + + // check to see if this is a potential framework bundle + if (!strstr(path, ".framework")) { + return; + } + + // My.framework/Versions/A/My for OS X + // My.framework/My for iOS + + NSString* frameworkPath = [NSString stringWithUTF8String:path]; +#if TARGET_OS_IPHONE + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; +#else + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework/Versions/A + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework/Versions + frameworkPath = [frameworkPath stringByDeletingLastPathComponent]; // My.framework +#endif + + NSBundle* const bundle = [NSBundle bundleWithPath:frameworkPath]; + + if (!bundle) { + return; + } + + FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(file, "bundle_id", [bundle bundleIdentifier]); + FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty( + file, "build_version", [bundle objectForInfoDictionaryKey:@"CFBundleVersion"]); + FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty( + file, "display_version", [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); +} + +static void FIRCLSBinaryImageRecordSlice(bool added, const FIRCLSBinaryImageDetails imageDetails) { + bool needsClosing = false; + if (!FIRCLSBinaryImageOpenIfNeeded(&needsClosing)) { + FIRCLSSDKLog("Error: unable to open binary image log file\n"); + return; + } + + FIRCLSFile* file = &_firclsContext.writable->binaryImage.file; + + FIRCLSFileWriteSectionStart(file, added ? "load" : "unload"); + + FIRCLSFileWriteHashStart(file); + + const char* path = FIRCLSMachOSliceGetExecutablePath((FIRCLSMachOSliceRef)&imageDetails.slice); + + FIRCLSFileWriteHashEntryString(file, "path", path); + + if (added) { + // this won't work if the binary has been unloaded + FIRCLSBinaryImageRecordLibraryFrameworkInfo(file, path); + } + + FIRCLSBinaryImageRecordDetails(file, imageDetails); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); + + if (needsClosing) { + FIRCLSFileClose(file); + } +} + +bool FIRCLSBinaryImageRecordMainExecutable(FIRCLSFile* file) { + FIRCLSBinaryImageDetails imageDetails; + + memset(&imageDetails, 0, sizeof(FIRCLSBinaryImageDetails)); + + imageDetails.slice = FIRCLSMachOSliceGetCurrent(); + FIRCLSBinaryImageFillInImageDetails(&imageDetails); + + FIRCLSFileWriteSectionStart(file, "executable"); + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "architecture", + FIRCLSMachOSliceGetArchitectureName(&imageDetails.slice)); + + FIRCLSBinaryImageRecordDetails(file, imageDetails); + FIRCLSFileWriteHashEntryBoolean(file, "encrypted", imageDetails.encrypted); + FIRCLSFileWriteHashEntryString(file, "minimum_sdk_version", + [FIRCLSMachOFormatVersion(&imageDetails.minSDK) UTF8String]); + FIRCLSFileWriteHashEntryString(file, "built_sdk_version", + [FIRCLSMachOFormatVersion(&imageDetails.builtSDK) UTF8String]); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); + + return true; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h new file mode 100644 index 00000000..f94e6333 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.h @@ -0,0 +1,121 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSException.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h" + +#include <dispatch/dispatch.h> +#include <stdbool.h> + +// The purpose of the crash context is to hold values that absolutely must be read and/or written at +// crash time. For robustness against memory corruption, they are protected with guard pages. +// Further, the context is seperated into read-only and read-write sections. + +__BEGIN_DECLS + +#ifdef __OBJC__ +@class FIRCLSInternalReport; +@class FIRCLSSettings; +@class FIRCLSInstallIdentifierModel; +@class FIRCLSFileManager; +#endif + +typedef struct { + volatile bool initialized; + volatile bool debuggerAttached; + const char* previouslyCrashedFileFullPath; + const char* logPath; +#if CLS_USE_SIGALTSTACK + void* signalStack; +#endif +#if CLS_MACH_EXCEPTION_SUPPORTED + void* machStack; +#endif + void* delegate; + void* callbackDelegate; + + FIRCLSBinaryImageReadOnlyContext binaryimage; + FIRCLSExceptionReadOnlyContext exception; + FIRCLSHostReadOnlyContext host; + FIRCLSSignalReadContext signal; +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSMachExceptionReadContext machException; +#endif + FIRCLSUserLoggingReadOnlyContext logging; +} FIRCLSReadOnlyContext; + +typedef struct { + FIRCLSInternalLoggingWritableContext internalLogging; + volatile bool crashOccurred; + FIRCLSBinaryImageReadWriteContext binaryImage; + FIRCLSUserLoggingWritableContext logging; + FIRCLSExceptionWritableContext exception; +} FIRCLSReadWriteContext; + +typedef struct { + FIRCLSReadOnlyContext* readonly; + FIRCLSReadWriteContext* writable; + FIRCLSAllocatorRef allocator; +} FIRCLSContext; + +typedef struct { + void* delegate; + const char* customBundleId; + const char* rootPath; + const char* previouslyCrashedFileRootPath; + const char* sessionId; + const char* installId; + const char* betaToken; +#if CLS_MACH_EXCEPTION_SUPPORTED + exception_mask_t machExceptionMask; +#endif + bool errorsEnabled; + bool customExceptionsEnabled; + uint32_t maxCustomExceptions; + uint32_t maxErrorLogSize; + uint32_t maxLogSize; + uint32_t maxKeyValues; +} FIRCLSContextInitData; + +#ifdef __OBJC__ +bool FIRCLSContextInitialize(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager); + +// Re-writes the metadata file on the current thread +void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager); +#endif + +void FIRCLSContextBaseInit(void); +void FIRCLSContextBaseDeinit(void); + +bool FIRCLSContextIsInitialized(void); +bool FIRCLSContextHasCrashed(void); +void FIRCLSContextMarkHasCrashed(void); +bool FIRCLSContextMarkAndCheckIfCrashed(void); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m new file mode 100644 index 00000000..d860e1fd --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSContext.m @@ -0,0 +1,469 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSContext.h" + +#include <stdlib.h> +#include <string.h> + +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" + +#include "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSProcess.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +// The writable size is our handler stack plus whatever scratch we need. We have to use this space +// extremely carefully, however, because thread stacks always needs to be page-aligned. Only the +// first allocation is gauranteed to be page-aligned. +// +// CLS_SIGNAL_HANDLER_STACK_SIZE and CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE are platform dependant, +// defined as 0 for tv/watch. +#define CLS_MINIMUM_READWRITE_SIZE \ + (CLS_SIGNAL_HANDLER_STACK_SIZE + CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE + \ + sizeof(FIRCLSReadWriteContext)) + +// We need enough space here for the context, plus storage for strings. +#define CLS_MINIMUM_READABLE_SIZE (sizeof(FIRCLSReadOnlyContext) + 4096 * 4) + +static const int64_t FIRCLSContextInitWaitTime = 5LL * NSEC_PER_SEC; + +static bool FIRCLSContextRecordMetadata(const char* path, const FIRCLSContextInitData* initData); +static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component); +static void FIRCLSContextAllocate(FIRCLSContext* context); + +FIRCLSContextInitData FIRCLSContextBuildInitData(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager) { + // Because we need to start the crash reporter right away, + // it starts up either with default settings, or cached settings + // from the last time they were fetched + + FIRCLSContextInitData initData; + + memset(&initData, 0, sizeof(FIRCLSContextInitData)); + + initData.customBundleId = nil; + initData.installId = [installIDModel.installID UTF8String]; + initData.sessionId = [[report identifier] UTF8String]; + initData.rootPath = [[report path] UTF8String]; + initData.previouslyCrashedFileRootPath = [[fileManager rootPath] UTF8String]; + initData.errorsEnabled = [settings errorReportingEnabled]; + initData.customExceptionsEnabled = [settings customExceptionsEnabled]; + initData.maxCustomExceptions = [settings maxCustomExceptions]; + initData.maxErrorLogSize = [settings errorLogBufferSize]; + initData.maxLogSize = [settings logBufferSize]; + initData.maxKeyValues = [settings maxCustomKeys]; + initData.betaToken = ""; + + // If this is set, then we could attempt to do a synchronous submission for certain kinds of + // events (exceptions). This is a very cool feature, but adds complexity to the backend. For now, + // we're going to leave this disabled. It does work in the exception case, but will ultimtely + // result in the following crash to be discared. Usually that crash isn't interesting. But, if it + // was, we'd never have a chance to see it. + initData.delegate = nil; + +#if CLS_MACH_EXCEPTION_SUPPORTED + __block exception_mask_t mask = 0; + + // TODO(b/141241224) This if statement was hardcoded to no, so this block was never run + // FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) { + // if ([self.delegate ensureDeliveryOfUnixSignal:signal]) { + // mask |= FIRCLSMachExceptionMaskForSignal(signal); + // } + // }); + + initData.machExceptionMask = mask; +#endif + + return initData; +} + +bool FIRCLSContextInitialize(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager) { + FIRCLSContextInitData initDataObj = + FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager); + FIRCLSContextInitData* initData = &initDataObj; + + if (!initData) { + return false; + } + + FIRCLSContextBaseInit(); + + dispatch_group_t group = dispatch_group_create(); + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + if (!FIRCLSIsValidPointer(initData->rootPath)) { + return false; + } + + NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath]; + + // setup our SDK log file synchronously, because other calls may depend on it + _firclsContext.readonly->logPath = FIRCLSContextAppendToRoot(rootPath, @"sdk.log"); + if (!FIRCLSUnlinkIfExists(_firclsContext.readonly->logPath)) { + FIRCLSErrorLog(@"Unable to write initialize SDK write paths %s", strerror(errno)); + } + + // some values that aren't tied to particular subsystem + _firclsContext.readonly->debuggerAttached = FIRCLSProcessDebuggerAttached(); + _firclsContext.readonly->delegate = initData->delegate; + + dispatch_group_async(group, queue, ^{ + FIRCLSHostInitialize(&_firclsContext.readonly->host); + }); + + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->logging.errorStorage.maxSize = 0; + _firclsContext.readonly->logging.errorStorage.maxEntries = + initData->errorsEnabled ? initData->maxCustomExceptions : 0; + _firclsContext.readonly->logging.errorStorage.restrictBySize = false; + _firclsContext.readonly->logging.errorStorage.entryCount = + &_firclsContext.writable->logging.errorsCount; + _firclsContext.readonly->logging.errorStorage.aPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportErrorAFile); + _firclsContext.readonly->logging.errorStorage.bPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportErrorBFile); + + _firclsContext.readonly->logging.logStorage.maxSize = initData->maxLogSize; + _firclsContext.readonly->logging.logStorage.maxEntries = 0; + _firclsContext.readonly->logging.logStorage.restrictBySize = true; + _firclsContext.readonly->logging.logStorage.entryCount = NULL; + _firclsContext.readonly->logging.logStorage.aPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportLogAFile); + _firclsContext.readonly->logging.logStorage.bPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportLogBFile); + _firclsContext.readonly->logging.customExceptionStorage.aPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportCustomExceptionAFile); + _firclsContext.readonly->logging.customExceptionStorage.bPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportCustomExceptionBFile); + _firclsContext.readonly->logging.customExceptionStorage.maxSize = 0; + _firclsContext.readonly->logging.customExceptionStorage.restrictBySize = false; + _firclsContext.readonly->logging.customExceptionStorage.maxEntries = + initData->maxCustomExceptions; + _firclsContext.readonly->logging.customExceptionStorage.entryCount = + &_firclsContext.writable->exception.customExceptionCount; + + _firclsContext.readonly->logging.userKVStorage.maxCount = initData->maxKeyValues; + _firclsContext.readonly->logging.userKVStorage.incrementalPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportUserIncrementalKVFile); + _firclsContext.readonly->logging.userKVStorage.compactedPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportUserCompactedKVFile); + + _firclsContext.readonly->logging.internalKVStorage.maxCount = 32; // Hardcode = bad + _firclsContext.readonly->logging.internalKVStorage.incrementalPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportInternalIncrementalKVFile); + _firclsContext.readonly->logging.internalKVStorage.compactedPath = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportInternalCompactedKVFile); + + FIRCLSUserLoggingInit(&_firclsContext.readonly->logging, &_firclsContext.writable->logging); + }); + + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->binaryimage.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportBinaryImageFile); + + FIRCLSBinaryImageInit(&_firclsContext.readonly->binaryimage, + &_firclsContext.writable->binaryImage); + }); + + dispatch_group_async(group, queue, ^{ + NSString* rootPath = [NSString stringWithUTF8String:initData->previouslyCrashedFileRootPath]; + NSString* fileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName]; + _firclsContext.readonly->previouslyCrashedFileFullPath = + FIRCLSContextAppendToRoot(rootPath, fileName); + }); + + if (!_firclsContext.readonly->debuggerAttached) { + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->signal.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportSignalFile); + + FIRCLSSignalInitialize(&_firclsContext.readonly->signal); + }); + +#if CLS_MACH_EXCEPTION_SUPPORTED + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->machException.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportMachExceptionFile); + + FIRCLSMachExceptionInit(&_firclsContext.readonly->machException, initData->machExceptionMask); + }); +#endif + + dispatch_group_async(group, queue, ^{ + _firclsContext.readonly->exception.path = + FIRCLSContextAppendToRoot(rootPath, FIRCLSReportExceptionFile); + _firclsContext.readonly->exception.maxCustomExceptions = + initData->customExceptionsEnabled ? initData->maxCustomExceptions : 0; + + FIRCLSExceptionInitialize(&_firclsContext.readonly->exception, + &_firclsContext.writable->exception, initData->delegate); + }); + } else { + FIRCLSSDKLog("Debugger present - not installing handlers\n"); + } + + dispatch_group_async(group, queue, ^{ + const char* metaDataPath = [[rootPath stringByAppendingPathComponent:FIRCLSReportMetadataFile] + fileSystemRepresentation]; + if (!FIRCLSContextRecordMetadata(metaDataPath, initData)) { + FIRCLSSDKLog("Unable to record context metadata\n"); + } + }); + + // At this point we need to do two things. First, we need to do our memory protection *only* after + // all of these initialization steps are really done. But, we also want to wait as long as + // possible for these to be complete. If we do not, there's a chance that we will not be able to + // correctly report a crash shortly after start. + + // Note at this will retain the group, so its totally fine to release the group here. + dispatch_group_notify(group, queue, ^{ + _firclsContext.readonly->initialized = true; + __sync_synchronize(); + + if (!FIRCLSAllocatorProtect(_firclsContext.allocator)) { + FIRCLSSDKLog("Error: Memory protection failed\n"); + } + }); + + if (dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, FIRCLSContextInitWaitTime)) != + 0) { + FIRCLSSDKLog("Error: Delayed initialization\n"); + } + + return true; +} + +void FIRCLSContextUpdateMetadata(FIRCLSInternalReport* report, + FIRCLSSettings* settings, + FIRCLSInstallIdentifierModel* installIDModel, + FIRCLSFileManager* fileManager) { + FIRCLSContextInitData initDataObj = + FIRCLSContextBuildInitData(report, settings, installIDModel, fileManager); + FIRCLSContextInitData* initData = &initDataObj; + + NSString* rootPath = [NSString stringWithUTF8String:initData->rootPath]; + + const char* metaDataPath = + [[rootPath stringByAppendingPathComponent:FIRCLSReportMetadataFile] fileSystemRepresentation]; + + if (!FIRCLSContextRecordMetadata(metaDataPath, initData)) { + FIRCLSErrorLog(@"Unable to update context metadata"); + } +} + +void FIRCLSContextBaseInit(void) { + NSString* sdkBundleID = FIRCLSApplicationGetSDKBundleID(); + + NSString* loggingQueueName = [sdkBundleID stringByAppendingString:@".logging"]; + NSString* binaryImagesQueueName = [sdkBundleID stringByAppendingString:@".binary-images"]; + NSString* exceptionQueueName = [sdkBundleID stringByAppendingString:@".exception"]; + + _firclsLoggingQueue = dispatch_queue_create([loggingQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + _firclsBinaryImageQueue = + dispatch_queue_create([binaryImagesQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + _firclsExceptionQueue = + dispatch_queue_create([exceptionQueueName UTF8String], DISPATCH_QUEUE_SERIAL); + + FIRCLSContextAllocate(&_firclsContext); + + _firclsContext.writable->internalLogging.logFd = -1; + _firclsContext.writable->internalLogging.logLevel = FIRCLSInternalLogLevelDebug; + _firclsContext.writable->crashOccurred = false; + + _firclsContext.readonly->initialized = false; + + __sync_synchronize(); +} + +static void FIRCLSContextAllocate(FIRCLSContext* context) { + // create the allocator, and the contexts + // The ordering here is really important, because the "stack" variable must be + // page-aligned. There's no mechanism to ask the allocator to do alignment, but we + // do know the very first allocation in a region is aligned to a page boundary. + + context->allocator = FIRCLSAllocatorCreate(CLS_MINIMUM_READWRITE_SIZE, CLS_MINIMUM_READABLE_SIZE); + + context->readonly = + FIRCLSAllocatorSafeAllocate(context->allocator, sizeof(FIRCLSReadOnlyContext), CLS_READONLY); + memset(context->readonly, 0, sizeof(FIRCLSReadOnlyContext)); + +#if CLS_MEMORY_PROTECTION_ENABLED +#if CLS_MACH_EXCEPTION_SUPPORTED + context->readonly->machStack = FIRCLSAllocatorSafeAllocate( + context->allocator, CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE, CLS_READWRITE); +#endif +#if CLS_USE_SIGALTSTACK + context->readonly->signalStack = + FIRCLSAllocatorSafeAllocate(context->allocator, CLS_SIGNAL_HANDLER_STACK_SIZE, CLS_READWRITE); +#endif +#else +#if CLS_MACH_EXCEPTION_SUPPORTED + context->readonly->machStack = valloc(CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE); +#endif +#if CLS_USE_SIGALTSTACK + context->readonly->signalStack = valloc(CLS_SIGNAL_HANDLER_STACK_SIZE); +#endif +#endif + +#if CLS_MACH_EXCEPTION_SUPPORTED + memset(_firclsContext.readonly->machStack, 0, CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE); +#endif +#if CLS_USE_SIGALTSTACK + memset(_firclsContext.readonly->signalStack, 0, CLS_SIGNAL_HANDLER_STACK_SIZE); +#endif + + context->writable = FIRCLSAllocatorSafeAllocate(context->allocator, + sizeof(FIRCLSReadWriteContext), CLS_READWRITE); + memset(context->writable, 0, sizeof(FIRCLSReadWriteContext)); +} + +void FIRCLSContextBaseDeinit(void) { + _firclsContext.readonly->initialized = false; + + FIRCLSAllocatorDestroy(_firclsContext.allocator); +} + +bool FIRCLSContextIsInitialized(void) { + __sync_synchronize(); + if (!FIRCLSIsValidPointer(_firclsContext.readonly)) { + return false; + } + + return _firclsContext.readonly->initialized; +} + +bool FIRCLSContextHasCrashed(void) { + if (!FIRCLSContextIsInitialized()) { + return false; + } + + // we've already run a full barrier above, so this read is ok + return _firclsContext.writable->crashOccurred; +} + +void FIRCLSContextMarkHasCrashed(void) { + if (!FIRCLSContextIsInitialized()) { + return; + } + + _firclsContext.writable->crashOccurred = true; + __sync_synchronize(); +} + +bool FIRCLSContextMarkAndCheckIfCrashed(void) { + if (!FIRCLSContextIsInitialized()) { + return false; + } + + if (_firclsContext.writable->crashOccurred) { + return true; + } + + _firclsContext.writable->crashOccurred = true; + __sync_synchronize(); + + return false; +} + +static const char* FIRCLSContextAppendToRoot(NSString* root, NSString* component) { + return FIRCLSDupString( + [[root stringByAppendingPathComponent:component] fileSystemRepresentation]); +} + +static bool FIRCLSContextRecordIdentity(FIRCLSFile* file, const FIRCLSContextInitData* initData) { + FIRCLSFileWriteSectionStart(file, "identity"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "generator", CLS_SDK_GENERATOR_NAME); + FIRCLSFileWriteHashEntryString(file, "display_version", CLS_SDK_DISPLAY_VERSION); + FIRCLSFileWriteHashEntryString(file, "build_version", CLS_SDK_DISPLAY_VERSION); + FIRCLSFileWriteHashEntryUint64(file, "started_at", time(NULL)); + + FIRCLSFileWriteHashEntryString(file, "session_id", initData->sessionId); + FIRCLSFileWriteHashEntryString(file, "install_id", initData->installId); + FIRCLSFileWriteHashEntryString(file, "beta_token", initData->betaToken); + FIRCLSFileWriteHashEntryBoolean(file, "absolute_log_timestamps", true); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); + + return true; +} + +static bool FIRCLSContextRecordApplication(FIRCLSFile* file, const char* customBundleId) { + FIRCLSFileWriteSectionStart(file, "application"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "bundle_id", + [FIRCLSApplicationGetBundleIdentifier() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "custom_bundle_id", customBundleId); + FIRCLSFileWriteHashEntryString(file, "build_version", + [FIRCLSApplicationGetBundleVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "display_version", + [FIRCLSApplicationGetShortBundleVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "extension_id", + [FIRCLSApplicationExtensionPointIdentifier() UTF8String]); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); + + return true; +} + +static bool FIRCLSContextRecordMetadata(const char* path, const FIRCLSContextInitData* initData) { + if (!FIRCLSUnlinkIfExists(path)) { + FIRCLSSDKLog("Unable to unlink existing metadata file %s\n", strerror(errno)); + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, path, false)) { + FIRCLSSDKLog("Unable to open metadata file %s\n", strerror(errno)); + return false; + } + + if (!FIRCLSContextRecordIdentity(&file, initData)) { + FIRCLSSDKLog("Unable to write out identity metadata\n"); + } + + if (!FIRCLSHostRecord(&file)) { + FIRCLSSDKLog("Unable to write out host metadata\n"); + } + + if (!FIRCLSContextRecordApplication(&file, initData->customBundleId)) { + FIRCLSSDKLog("Unable to write out application metadata\n"); + } + + if (!FIRCLSBinaryImageRecordMainExecutable(&file)) { + FIRCLSSDKLog("Unable to write out executable metadata\n"); + } + + FIRCLSFileClose(&file); + + return true; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c new file mode 100644 index 00000000..b9401392 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.c @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +const char *FIRCLSCrashedMarkerFileName = "previously-crashed"; + +void FIRCLSCreateCrashedMarkerFile() { + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, _firclsContext.readonly->previouslyCrashedFileFullPath, false)) { + FIRCLSSDKLog("Unable to create the crashed marker file\n"); + return; + } + + FIRCLSFileClose(&file); + FIRCLSSDKLog("Created the crashed marker file\n"); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h new file mode 100644 index 00000000..ccf42767 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h @@ -0,0 +1,19 @@ +// Copyright 2019 Google +// +// 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. + +#include <stdio.h> + +extern const char *FIRCLSCrashedMarkerFileName; + +void FIRCLSCreateCrashedMarkerFile(void); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h new file mode 100644 index 00000000..10173ed4 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSGlobals.h @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSContext.h" + +__BEGIN_DECLS + +extern FIRCLSContext _firclsContext; +extern dispatch_queue_t _firclsLoggingQueue; +extern dispatch_queue_t _firclsBinaryImageQueue; +extern dispatch_queue_t _firclsExceptionQueue; + +#define FIRCLSGetLoggingQueue() (_firclsLoggingQueue) +#define FIRCLSGetBinaryImageQueue() (_firclsBinaryImageQueue) +#define FIRCLSGetExceptionQueue() (_firclsExceptionQueue) + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h new file mode 100644 index 00000000..b647ca03 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.h @@ -0,0 +1,37 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <mach/vm_types.h> +#include <sys/cdefs.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +typedef struct { + const char* documentDirectoryPath; + vm_size_t pageSize; +} FIRCLSHostReadOnlyContext; + +__BEGIN_DECLS + +void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext); + +vm_size_t FIRCLSHostGetPageSize(void); + +bool FIRCLSHostRecord(FIRCLSFile* file); + +void FIRCLSHostWriteDiskUsage(FIRCLSFile* file); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m new file mode 100644 index 00000000..ffe206e1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSHost.m @@ -0,0 +1,161 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h" + +#include <mach/mach.h> +#include <sys/mount.h> +#include <sys/sysctl.h> + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#import "Crashlytics/Shared/FIRCLSFABHost.h" + +#if TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#else +#import <Cocoa/Cocoa.h> +#endif + +#define CLS_HOST_SYSCTL_BUFFER_SIZE (128) + +#if CLS_CPU_ARM64 +#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 16) +#else +// return 4K, which is correct for all platforms except arm64, currently +#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 4) +#endif +#define CLS_MIN_NATIVE_PAGE_SIZE (1024 * 4) + +#pragma mark Prototypes +static void FIRCLSHostWriteSysctlEntry( + FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize); +static void FIRCLSHostWriteModelInfo(FIRCLSFile* file); +static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file); + +#pragma mark - API +void FIRCLSHostInitialize(FIRCLSHostReadOnlyContext* roContext) { + _firclsContext.readonly->host.pageSize = FIRCLSHostGetPageSize(); + _firclsContext.readonly->host.documentDirectoryPath = NULL; + + // determine where the document directory is mounted, so we can get file system statistics later + NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + if ([paths count]) { + _firclsContext.readonly->host.documentDirectoryPath = + FIRCLSDupString([[paths objectAtIndex:0] fileSystemRepresentation]); + } +} + +vm_size_t FIRCLSHostGetPageSize(void) { + size_t size; + int pageSize; + + // hw.pagesize is defined as HW_PAGESIZE, which is an int. It's important to match + // these types. Turns out that sysctl will not init the data to zero, but it appears + // that sysctlbyname does. This API is nicer, but that's important to keep in mind. + + pageSize = 0; + size = sizeof(pageSize); + if (sysctlbyname("hw.pagesize", &pageSize, &size, NULL, 0) != 0) { + FIRCLSSDKLog("sysctlbyname failed while trying to get hw.pagesize\n"); + + return CLS_MAX_NATIVE_PAGE_SIZE; + } + + // if the returned size is not the expected value, abort + if (size != sizeof(pageSize)) { + return CLS_MAX_NATIVE_PAGE_SIZE; + } + + // put in some guards to make sure our size is reasonable + if (pageSize > CLS_MAX_NATIVE_PAGE_SIZE) { + return CLS_MAX_NATIVE_PAGE_SIZE; + } + + if (pageSize < CLS_MIN_NATIVE_PAGE_SIZE) { + return CLS_MIN_NATIVE_PAGE_SIZE; + } + + return pageSize; +} + +static void FIRCLSHostWriteSysctlEntry( + FIRCLSFile* file, const char* key, const char* sysctlKey, void* buffer, size_t bufferSize) { + if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) { + FIRCLSFileWriteHashEntryString(file, key, "(failed)"); + return; + } + + FIRCLSFileWriteHashEntryString(file, key, buffer); +} + +static void FIRCLSHostWriteModelInfo(FIRCLSFile* file) { + FIRCLSFileWriteHashEntryString(file, "model", [FIRCLSHostModelInfo() UTF8String]); + + // allocate a static buffer for the sysctl values, which are typically + // quite short + char buffer[CLS_HOST_SYSCTL_BUFFER_SIZE]; + +#if TARGET_OS_EMBEDDED + FIRCLSHostWriteSysctlEntry(file, "machine", "hw.model", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE); +#else + FIRCLSHostWriteSysctlEntry(file, "machine", "hw.machine", buffer, CLS_HOST_SYSCTL_BUFFER_SIZE); + FIRCLSHostWriteSysctlEntry(file, "cpu", "machdep.cpu.brand_string", buffer, + CLS_HOST_SYSCTL_BUFFER_SIZE); +#endif +} + +static void FIRCLSHostWriteOSVersionInfo(FIRCLSFile* file) { + FIRCLSFileWriteHashEntryString(file, "os_build_version", [FIRCLSHostOSBuildVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "os_display_version", + [FIRCLSHostOSDisplayVersion() UTF8String]); + FIRCLSFileWriteHashEntryString(file, "platform", [FIRCLSApplicationGetPlatform() UTF8String]); +} + +bool FIRCLSHostRecord(FIRCLSFile* file) { + FIRCLSFileWriteSectionStart(file, "host"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSHostWriteModelInfo(file); + FIRCLSHostWriteOSVersionInfo(file); + FIRCLSFileWriteHashEntryString(file, "locale", + [[[NSLocale currentLocale] localeIdentifier] UTF8String]); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); + + return true; +} + +void FIRCLSHostWriteDiskUsage(FIRCLSFile* file) { + struct statfs tStats; + + FIRCLSFileWriteSectionStart(file, "storage"); + + FIRCLSFileWriteHashStart(file); + + if (statfs(_firclsContext.readonly->host.documentDirectoryPath, &tStats) == 0) { + FIRCLSFileWriteHashEntryUint64(file, "free", tStats.f_bavail * tStats.f_bsize); + FIRCLSFileWriteHashEntryUint64(file, "total", tStats.f_blocks * tStats.f_bsize); + } + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c new file mode 100644 index 00000000..fff11a07 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.c @@ -0,0 +1,824 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSProcess.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <dispatch/dispatch.h> +#include <objc/message.h> +#include <pthread.h> +#include <sys/sysctl.h> + +#define THREAD_NAME_BUFFER_SIZE (64) + +#pragma mark Prototypes +static bool FIRCLSProcessGetThreadName(FIRCLSProcess *process, + thread_t thread, + char *buffer, + size_t length); +static const char *FIRCLSProcessGetThreadDispatchQueueName(FIRCLSProcess *process, thread_t thread); + +#pragma mark - API +bool FIRCLSProcessInit(FIRCLSProcess *process, thread_t crashedThread, void *uapVoid) { + if (!process) { + return false; + } + + process->task = mach_task_self(); + process->thisThread = mach_thread_self(); + process->crashedThread = crashedThread; + process->uapVoid = uapVoid; + + if (task_threads(process->task, &process->threads, &process->threadCount) != KERN_SUCCESS) { + // failed to get all threads + process->threadCount = 0; + FIRCLSSDKLog("Error: unable to get task threads\n"); + + return false; + } + + return true; +} + +bool FIRCLSProcessDestroy(FIRCLSProcess *process) { + return false; +} + +// https://developer.apple.com/library/mac/#qa/qa2004/qa1361.html +bool FIRCLSProcessDebuggerAttached(void) { + int junk; + int mib[4]; + struct kinfo_proc info; + size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + size = sizeof(info); + junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); + if (junk != 0) { + FIRCLSSDKLog("sysctl failed while trying to get kinfo_proc\n"); + return false; + } + + // We're being debugged if the P_TRACED flag is set. + return (info.kp_proc.p_flag & P_TRACED) != 0; +} + +#pragma mark - Thread Support +static bool FIRCLSProcessIsCurrentThread(FIRCLSProcess *process, thread_t thread) { + return MACH_PORT_INDEX(process->thisThread) == MACH_PORT_INDEX(thread); +} + +static bool FIRCLSProcessIsCrashedThread(FIRCLSProcess *process, thread_t thread) { + return MACH_PORT_INDEX(process->crashedThread) == MACH_PORT_INDEX(thread); +} + +static uint32_t FIRCLSProcessGetThreadCount(FIRCLSProcess *process) { + return process->threadCount; +} + +static thread_t FIRCLSProcessGetThread(FIRCLSProcess *process, uint32_t index) { + if (index >= process->threadCount) { + return MACH_PORT_NULL; + } + + return process->threads[index]; +} + +bool FIRCLSProcessSuspendAllOtherThreads(FIRCLSProcess *process) { + mach_msg_type_number_t i; + bool success; + + success = true; + for (i = 0; i < process->threadCount; ++i) { + thread_t thread; + + thread = FIRCLSProcessGetThread(process, i); + + if (FIRCLSProcessIsCurrentThread(process, thread)) { + continue; + } + + // FIXME: workaround to get this building on watch, but we need to suspend/resume threads! +#if CLS_CAN_SUSPEND_THREADS + success = success && (thread_suspend(thread) == KERN_SUCCESS); +#endif + } + + return success; +} + +bool FIRCLSProcessResumeAllOtherThreads(FIRCLSProcess *process) { + mach_msg_type_number_t i; + bool success; + + success = true; + for (i = 0; i < process->threadCount; ++i) { + thread_t thread; + + thread = FIRCLSProcessGetThread(process, i); + + if (FIRCLSProcessIsCurrentThread(process, thread)) { + continue; + } + + // FIXME: workaround to get this building on watch, but we need to suspend/resume threads! +#if CLS_CAN_SUSPEND_THREADS + success = success && (thread_resume(thread) == KERN_SUCCESS); +#endif + } + + return success; +} + +#pragma mark - Thread Properties +void *FIRCLSThreadGetCurrentPC(void) { + return __builtin_return_address(0); +} + +static bool FIRCLSProcessGetThreadState(FIRCLSProcess *process, + thread_t thread, + FIRCLSThreadContext *context) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLogError("invalid context supplied"); + return false; + } + + // If the thread context we should use is non-NULL, then just assign it here. Otherwise, + // query the thread state + if (FIRCLSProcessIsCrashedThread(process, thread) && FIRCLSIsValidPointer(process->uapVoid)) { + *context = *((_STRUCT_UCONTEXT *)process->uapVoid)->uc_mcontext; + return true; + } + + // Here's a wild trick: emulate what thread_get_state would do. It apppears that + // we cannot reliably unwind out of thread_get_state. So, instead of trying, setup + // a thread context that resembles what the real thing would look like + if (FIRCLSProcessIsCurrentThread(process, thread)) { + FIRCLSSDKLog("Faking current thread\n"); + memset(context, 0, sizeof(FIRCLSThreadContext)); + + // Compute the frame address, and then base the stack value off of that. A frame pushes + // two pointers onto the stack, so we have to offset. + const uintptr_t frameAddress = (uintptr_t)__builtin_frame_address(0); + const uintptr_t stackAddress = FIRCLSUnwindStackPointerFromFramePointer(frameAddress); + +#if CLS_CPU_X86_64 + context->__ss.__rip = (uintptr_t)FIRCLSThreadGetCurrentPC(); + context->__ss.__rbp = frameAddress; + context->__ss.__rsp = stackAddress; +#elif CLS_CPU_I386 + context->__ss.__eip = (uintptr_t)FIRCLSThreadGetCurrentPC(); + context->__ss.__ebp = frameAddress; + context->__ss.__esp = stackAddress; +#elif CLS_CPU_ARM64 + FIRCLSThreadContextSetPC(context, (uintptr_t)FIRCLSThreadGetCurrentPC()); + FIRCLSThreadContextSetFramePointer(context, frameAddress); + FIRCLSThreadContextSetLinkRegister(context, (uintptr_t)__builtin_return_address(0)); + FIRCLSThreadContextSetStackPointer(context, stackAddress); +#elif CLS_CPU_ARM + context->__ss.__pc = (uintptr_t)FIRCLSThreadGetCurrentPC(); + context->__ss.__r[7] = frameAddress; + context->__ss.__lr = (uintptr_t)__builtin_return_address(0); + context->__ss.__sp = stackAddress; +#endif + + return true; + } + +#if !TARGET_OS_WATCH + // try to get the value by querying the thread state + mach_msg_type_number_t stateCount = FIRCLSThreadStateCount; + if (thread_get_state(thread, FIRCLSThreadState, (thread_state_t)(&(context->__ss)), + &stateCount) != KERN_SUCCESS) { + FIRCLSSDKLogError("failed to get thread state\n"); + return false; + } + + return true; +#else + return false; +#endif +} + +static bool FIRCLSProcessGetThreadName(FIRCLSProcess *process, + thread_t thread, + char *buffer, + size_t length) { + pthread_t pthread; + + if (!buffer || length <= 0) { + return false; + } + + pthread = pthread_from_mach_thread_np(thread); + + return pthread_getname_np(pthread, buffer, length) == 0; +} + +static const char *FIRCLSProcessGetThreadDispatchQueueName(FIRCLSProcess *process, + thread_t thread) { + thread_identifier_info_data_t info; + mach_msg_type_number_t infoCount; + dispatch_queue_t *queueAddress; + dispatch_queue_t queue; + const char *string; + + infoCount = THREAD_IDENTIFIER_INFO_COUNT; + if (thread_info(thread, THREAD_IDENTIFIER_INFO, (thread_info_t)&info, &infoCount) != + KERN_SUCCESS) { + FIRCLSSDKLog("unable to get thread info\n"); + return NULL; + } + + queueAddress = (dispatch_queue_t *)info.dispatch_qaddr; + if (queueAddress == NULL) { + return ""; + } + + // Sometimes a queue address is invalid. I cannot explain why this is, but + // it can cause a crash. + if (!FIRCLSReadMemory((vm_address_t)queueAddress, &queue, sizeof(void *))) { + return ""; + } + + // here, we know it is safe to de-reference this address, so attempt to get the queue name + if (!queue) { + return ""; + } + + string = dispatch_queue_get_label(queue); + + // but, we still don't if the entire string is valid, so check that too + if (!FIRCLSReadString((vm_address_t)string, (char **)&string, 128)) { + return ""; + } + + return string; +} + +#pragma mark - Data Recording +static bool FIRCLSProcessRecordThreadRegisters(FIRCLSThreadContext context, FIRCLSFile *file) { +#if CLS_CPU_ARM + FIRCLSFileWriteHashEntryUint64(file, "r0", context.__ss.__r[0]); + FIRCLSFileWriteHashEntryUint64(file, "r1", context.__ss.__r[1]); + FIRCLSFileWriteHashEntryUint64(file, "r2", context.__ss.__r[2]); + FIRCLSFileWriteHashEntryUint64(file, "r3", context.__ss.__r[3]); + FIRCLSFileWriteHashEntryUint64(file, "r4", context.__ss.__r[4]); + FIRCLSFileWriteHashEntryUint64(file, "r5", context.__ss.__r[5]); + FIRCLSFileWriteHashEntryUint64(file, "r6", context.__ss.__r[6]); + FIRCLSFileWriteHashEntryUint64(file, "r7", context.__ss.__r[7]); + FIRCLSFileWriteHashEntryUint64(file, "r8", context.__ss.__r[8]); + FIRCLSFileWriteHashEntryUint64(file, "r9", context.__ss.__r[9]); + FIRCLSFileWriteHashEntryUint64(file, "r10", context.__ss.__r[10]); + FIRCLSFileWriteHashEntryUint64(file, "r11", context.__ss.__r[11]); + FIRCLSFileWriteHashEntryUint64(file, "ip", context.__ss.__r[12]); + FIRCLSFileWriteHashEntryUint64(file, "sp", context.__ss.__sp); + FIRCLSFileWriteHashEntryUint64(file, "lr", context.__ss.__lr); + FIRCLSFileWriteHashEntryUint64(file, "pc", context.__ss.__pc); + FIRCLSFileWriteHashEntryUint64(file, "cpsr", context.__ss.__cpsr); +#elif CLS_CPU_ARM64 + FIRCLSFileWriteHashEntryUint64(file, "x0", context.__ss.__x[0]); + FIRCLSFileWriteHashEntryUint64(file, "x1", context.__ss.__x[1]); + FIRCLSFileWriteHashEntryUint64(file, "x2", context.__ss.__x[2]); + FIRCLSFileWriteHashEntryUint64(file, "x3", context.__ss.__x[3]); + FIRCLSFileWriteHashEntryUint64(file, "x4", context.__ss.__x[4]); + FIRCLSFileWriteHashEntryUint64(file, "x5", context.__ss.__x[5]); + FIRCLSFileWriteHashEntryUint64(file, "x6", context.__ss.__x[6]); + FIRCLSFileWriteHashEntryUint64(file, "x7", context.__ss.__x[7]); + FIRCLSFileWriteHashEntryUint64(file, "x8", context.__ss.__x[8]); + FIRCLSFileWriteHashEntryUint64(file, "x9", context.__ss.__x[9]); + FIRCLSFileWriteHashEntryUint64(file, "x10", context.__ss.__x[10]); + FIRCLSFileWriteHashEntryUint64(file, "x11", context.__ss.__x[11]); + FIRCLSFileWriteHashEntryUint64(file, "x12", context.__ss.__x[12]); + FIRCLSFileWriteHashEntryUint64(file, "x13", context.__ss.__x[13]); + FIRCLSFileWriteHashEntryUint64(file, "x14", context.__ss.__x[14]); + FIRCLSFileWriteHashEntryUint64(file, "x15", context.__ss.__x[15]); + FIRCLSFileWriteHashEntryUint64(file, "x16", context.__ss.__x[16]); + FIRCLSFileWriteHashEntryUint64(file, "x17", context.__ss.__x[17]); + FIRCLSFileWriteHashEntryUint64(file, "x18", context.__ss.__x[18]); + FIRCLSFileWriteHashEntryUint64(file, "x19", context.__ss.__x[19]); + FIRCLSFileWriteHashEntryUint64(file, "x20", context.__ss.__x[20]); + FIRCLSFileWriteHashEntryUint64(file, "x21", context.__ss.__x[21]); + FIRCLSFileWriteHashEntryUint64(file, "x22", context.__ss.__x[22]); + FIRCLSFileWriteHashEntryUint64(file, "x23", context.__ss.__x[23]); + FIRCLSFileWriteHashEntryUint64(file, "x24", context.__ss.__x[24]); + FIRCLSFileWriteHashEntryUint64(file, "x25", context.__ss.__x[25]); + FIRCLSFileWriteHashEntryUint64(file, "x26", context.__ss.__x[26]); + FIRCLSFileWriteHashEntryUint64(file, "x27", context.__ss.__x[27]); + FIRCLSFileWriteHashEntryUint64(file, "x28", context.__ss.__x[28]); + FIRCLSFileWriteHashEntryUint64(file, "fp", FIRCLSThreadContextGetFramePointer(&context)); + FIRCLSFileWriteHashEntryUint64(file, "sp", FIRCLSThreadContextGetStackPointer(&context)); + FIRCLSFileWriteHashEntryUint64(file, "lr", FIRCLSThreadContextGetLinkRegister(&context)); + FIRCLSFileWriteHashEntryUint64(file, "pc", FIRCLSThreadContextGetPC(&context)); + FIRCLSFileWriteHashEntryUint64(file, "cpsr", context.__ss.__cpsr); +#elif CLS_CPU_I386 + FIRCLSFileWriteHashEntryUint64(file, "eax", context.__ss.__eax); + FIRCLSFileWriteHashEntryUint64(file, "ebx", context.__ss.__ebx); + FIRCLSFileWriteHashEntryUint64(file, "ecx", context.__ss.__ecx); + FIRCLSFileWriteHashEntryUint64(file, "edx", context.__ss.__edx); + FIRCLSFileWriteHashEntryUint64(file, "edi", context.__ss.__edi); + FIRCLSFileWriteHashEntryUint64(file, "esi", context.__ss.__esi); + FIRCLSFileWriteHashEntryUint64(file, "ebp", context.__ss.__ebp); + FIRCLSFileWriteHashEntryUint64(file, "esp", context.__ss.__esp); + FIRCLSFileWriteHashEntryUint64(file, "ss", context.__ss.__ss); + FIRCLSFileWriteHashEntryUint64(file, "eflags", context.__ss.__eflags); + FIRCLSFileWriteHashEntryUint64(file, "eip", context.__ss.__eip); + FIRCLSFileWriteHashEntryUint64(file, "cs", context.__ss.__cs); + FIRCLSFileWriteHashEntryUint64(file, "ds", context.__ss.__ds); + FIRCLSFileWriteHashEntryUint64(file, "es", context.__ss.__es); + FIRCLSFileWriteHashEntryUint64(file, "fs", context.__ss.__fs); + FIRCLSFileWriteHashEntryUint64(file, "gs", context.__ss.__gs); + + // how do we get the cr2 register? +#elif CLS_CPU_X86_64 + FIRCLSFileWriteHashEntryUint64(file, "rax", context.__ss.__rax); + FIRCLSFileWriteHashEntryUint64(file, "rbx", context.__ss.__rbx); + FIRCLSFileWriteHashEntryUint64(file, "rcx", context.__ss.__rcx); + FIRCLSFileWriteHashEntryUint64(file, "rdx", context.__ss.__rdx); + FIRCLSFileWriteHashEntryUint64(file, "rdi", context.__ss.__rdi); + FIRCLSFileWriteHashEntryUint64(file, "rsi", context.__ss.__rsi); + FIRCLSFileWriteHashEntryUint64(file, "rbp", context.__ss.__rbp); + FIRCLSFileWriteHashEntryUint64(file, "rsp", context.__ss.__rsp); + FIRCLSFileWriteHashEntryUint64(file, "r8", context.__ss.__r8); + FIRCLSFileWriteHashEntryUint64(file, "r9", context.__ss.__r9); + FIRCLSFileWriteHashEntryUint64(file, "r10", context.__ss.__r10); + FIRCLSFileWriteHashEntryUint64(file, "r11", context.__ss.__r11); + FIRCLSFileWriteHashEntryUint64(file, "r12", context.__ss.__r12); + FIRCLSFileWriteHashEntryUint64(file, "r13", context.__ss.__r13); + FIRCLSFileWriteHashEntryUint64(file, "r14", context.__ss.__r14); + FIRCLSFileWriteHashEntryUint64(file, "r15", context.__ss.__r15); + FIRCLSFileWriteHashEntryUint64(file, "rip", context.__ss.__rip); + FIRCLSFileWriteHashEntryUint64(file, "rflags", context.__ss.__rflags); + FIRCLSFileWriteHashEntryUint64(file, "cs", context.__ss.__cs); + FIRCLSFileWriteHashEntryUint64(file, "fs", context.__ss.__fs); + FIRCLSFileWriteHashEntryUint64(file, "gs", context.__ss.__gs); +#endif + + return true; +} + +static bool FIRCLSProcessRecordThread(FIRCLSProcess *process, thread_t thread, FIRCLSFile *file) { + FIRCLSUnwindContext unwindContext; + FIRCLSThreadContext context; + + if (!FIRCLSProcessGetThreadState(process, thread, &context)) { + FIRCLSSDKLogError("unable to get thread state"); + return false; + } + + if (!FIRCLSUnwindInit(&unwindContext, context)) { + FIRCLSSDKLog("unable to init unwind context\n"); + + return false; + } + + FIRCLSFileWriteHashStart(file); + + // registers + FIRCLSFileWriteHashKey(file, "registers"); + FIRCLSFileWriteHashStart(file); + + FIRCLSProcessRecordThreadRegisters(context, file); + + FIRCLSFileWriteHashEnd(file); + + // stacktrace + FIRCLSFileWriteHashKey(file, "stacktrace"); + + // stacktrace is an array of integers + FIRCLSFileWriteArrayStart(file); + + uint32_t repeatedPCCount = 0; + uint64_t repeatedPC = 0; + const FIRCLSInternalLogLevel level = _firclsContext.writable->internalLogging.logLevel; + + while (FIRCLSUnwindNextFrame(&unwindContext)) { + const uintptr_t pc = FIRCLSUnwindGetPC(&unwindContext); + const uint32_t frameCount = FIRCLSUnwindGetFrameRepeatCount(&unwindContext); + + if (repeatedPC == pc && repeatedPC != 0) { + // actively counting a recursion + repeatedPCCount = frameCount; + continue; + } + + if (frameCount >= FIRCLSUnwindInfiniteRecursionCountThreshold && repeatedPC == 0) { + repeatedPC = pc; + FIRCLSSDKLogWarn("Possible infinite recursion - suppressing logging\n"); + _firclsContext.writable->internalLogging.logLevel = FIRCLSInternalLogLevelWarn; + continue; + } + + if (repeatedPC != 0) { + // at this point, we've recorded a repeated PC, but it is now no longer + // repeating, so we can restore the logging + _firclsContext.writable->internalLogging.logLevel = level; + } + + FIRCLSFileWriteArrayEntryUint64(file, pc); + } + + FIRCLSFileWriteArrayEnd(file); + + // crashed? + if (FIRCLSProcessIsCrashedThread(process, thread)) { + FIRCLSFileWriteHashEntryBoolean(file, "crashed", true); + } + + if (repeatedPC != 0) { + FIRCLSFileWriteHashEntryUint64(file, "repeated_pc", repeatedPC); + FIRCLSFileWriteHashEntryUint64(file, "repeat_count", repeatedPCCount); + } + + // Just for extra safety, restore the logging level again. The logic + // above is fairly tricky, this is cheap, and no logging is a real pain. + _firclsContext.writable->internalLogging.logLevel = level; + + // end thread info + FIRCLSFileWriteHashEnd(file); + + return true; +} + +bool FIRCLSProcessRecordAllThreads(FIRCLSProcess *process, FIRCLSFile *file) { + uint32_t threadCount; + uint32_t i; + + threadCount = FIRCLSProcessGetThreadCount(process); + + FIRCLSFileWriteSectionStart(file, "threads"); + + FIRCLSFileWriteArrayStart(file); + + for (i = 0; i < threadCount; ++i) { + thread_t thread; + + thread = FIRCLSProcessGetThread(process, i); + + FIRCLSSDKLogInfo("recording thread %d data\n", i); + if (!FIRCLSProcessRecordThread(process, thread, file)) { + return false; + } + } + + FIRCLSFileWriteArrayEnd(file); + + FIRCLSFileWriteSectionEnd(file); + + FIRCLSSDKLogInfo("completed recording all thread data\n"); + + return true; +} + +void FIRCLSProcessRecordThreadNames(FIRCLSProcess *process, FIRCLSFile *file) { + uint32_t threadCount; + uint32_t i; + + FIRCLSFileWriteSectionStart(file, "thread_names"); + + FIRCLSFileWriteArrayStart(file); + + threadCount = FIRCLSProcessGetThreadCount(process); + for (i = 0; i < threadCount; ++i) { + thread_t thread; + char name[THREAD_NAME_BUFFER_SIZE]; + + thread = FIRCLSProcessGetThread(process, i); + + name[0] = 0; // null-terminate, just in case nothing is written + + FIRCLSProcessGetThreadName(process, thread, name, THREAD_NAME_BUFFER_SIZE); + + FIRCLSFileWriteArrayEntryString(file, name); + } + + FIRCLSFileWriteArrayEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSProcessRecordDispatchQueueNames(FIRCLSProcess *process, FIRCLSFile *file) { + uint32_t threadCount; + uint32_t i; + + FIRCLSFileWriteSectionStart(file, "dispatch_queue_names"); + + FIRCLSFileWriteArrayStart(file); + + threadCount = FIRCLSProcessGetThreadCount(process); + for (i = 0; i < threadCount; ++i) { + thread_t thread; + const char *name; + + thread = FIRCLSProcessGetThread(process, i); + + name = FIRCLSProcessGetThreadDispatchQueueName(process, thread); + + FIRCLSFileWriteArrayEntryString(file, name); + } + + FIRCLSFileWriteArrayEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +#pragma mark - Othe Process Info +bool FIRCLSProcessGetMemoryUsage(uint64_t *active, + uint64_t *inactive, + uint64_t *wired, + uint64_t *freeMem) { + mach_port_t hostPort; + mach_msg_type_number_t hostSize; + vm_size_t pageSize; + vm_statistics_data_t vmStat; + + hostPort = mach_host_self(); + + hostSize = sizeof(vm_statistics_data_t) / sizeof(integer_t); + + pageSize = _firclsContext.readonly->host.pageSize; + + if (host_statistics(hostPort, HOST_VM_INFO, (host_info_t)&vmStat, &hostSize) != KERN_SUCCESS) { + FIRCLSSDKLog("Failed to get vm statistics\n"); + return false; + } + + if (!(active && inactive && wired && freeMem)) { + FIRCLSSDKLog("Invalid pointers\n"); + return false; + } + + // compute the sizes in bytes and return the values + *active = vmStat.active_count * pageSize; + *inactive = vmStat.inactive_count * pageSize; + *wired = vmStat.wire_count * pageSize; + *freeMem = vmStat.free_count * pageSize; + + return true; +} + +bool FIRCLSProcessGetInfo(FIRCLSProcess *process, + uint64_t *virtualSize, + uint64_t *residentSize, + time_value_t *userTime, + time_value_t *systemTime) { + struct task_basic_info_64 taskInfo; + mach_msg_type_number_t count; + + count = TASK_BASIC_INFO_64_COUNT; + if (task_info(process->task, TASK_BASIC_INFO_64, (task_info_t)&taskInfo, &count) != + KERN_SUCCESS) { + FIRCLSSDKLog("Failed to get task info\n"); + return false; + } + + if (!(virtualSize && residentSize && userTime && systemTime)) { + FIRCLSSDKLog("Invalid pointers\n"); + return false; + } + + *virtualSize = taskInfo.virtual_size; + *residentSize = taskInfo.resident_size; + *userTime = taskInfo.user_time; + *systemTime = taskInfo.system_time; + + return true; +} + +void FIRCLSProcessRecordStats(FIRCLSProcess *process, FIRCLSFile *file) { + uint64_t active; + uint64_t inactive; + uint64_t virtualSize; + uint64_t residentSize; + uint64_t wired; + uint64_t freeMem; + time_value_t userTime; + time_value_t systemTime; + + if (!FIRCLSProcessGetMemoryUsage(&active, &inactive, &wired, &freeMem)) { + FIRCLSSDKLog("Unable to get process memory usage\n"); + return; + } + + if (!FIRCLSProcessGetInfo(process, &virtualSize, &residentSize, &userTime, &systemTime)) { + FIRCLSSDKLog("Unable to get process stats\n"); + return; + } + + FIRCLSFileWriteSectionStart(file, "process_stats"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryUint64(file, "active", active); + FIRCLSFileWriteHashEntryUint64(file, "inactive", inactive); + FIRCLSFileWriteHashEntryUint64(file, "wired", wired); + FIRCLSFileWriteHashEntryUint64(file, "freeMem", freeMem); // Intentionally left in, for now. Arg. + FIRCLSFileWriteHashEntryUint64(file, "free_mem", freeMem); + FIRCLSFileWriteHashEntryUint64(file, "virtual", virtualSize); + FIRCLSFileWriteHashEntryUint64(file, "resident", active); + FIRCLSFileWriteHashEntryUint64(file, "user_time", + (userTime.seconds * 1000 * 1000) + userTime.microseconds); + FIRCLSFileWriteHashEntryUint64(file, "sys_time", + (systemTime.seconds * 1000 * 1000) + systemTime.microseconds); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} + +#pragma mark - Runtime Info +#define OBJC_MSG_SEND_START ((vm_address_t)objc_msgSend) +#define OBJC_MSG_SEND_SUPER_START ((vm_address_t)objc_msgSendSuper) +#define OBJC_MSG_SEND_END (OBJC_MSG_SEND_START + 66) +#define OBJC_MSG_SEND_SUPER_END (OBJC_MSG_SEND_SUPER_START + 66) + +#if !CLS_CPU_ARM64 +#define OBJC_MSG_SEND_STRET_START ((vm_address_t)objc_msgSend_stret) +#define OBJC_MSG_SEND_SUPER_STRET_START ((vm_address_t)objc_msgSendSuper_stret) +#define OBJC_MSG_SEND_STRET_END (OBJC_MSG_SEND_STRET_START + 66) +#define OBJC_MSG_SEND_SUPER_STRET_END (OBJC_MSG_SEND_SUPER_STRET_START + 66) +#endif + +#if CLS_CPU_X86 +#define OBJC_MSG_SEND_FPRET_START ((vm_address_t)objc_msgSend_fpret) +#define OBJC_MSG_SEND_FPRET_END (OBJC_MSG_SEND_FPRET_START + 66) +#endif + +static const char *FIRCLSProcessGetObjCSelectorName(FIRCLSThreadContext registers) { + void *selectorAddress; + void *selRegister; +#if !CLS_CPU_ARM64 + void *stretSelRegister; +#endif + vm_address_t pc; + + // First, did we crash in objc_msgSend? The two ways I can think + // of doing this are to use dladdr, and then comparing the strings to + // objc_msg*, or looking up the symbols, and guessing if we are "close enough". + + selectorAddress = NULL; + +#if CLS_CPU_ARM + pc = registers.__ss.__pc; + selRegister = (void *)registers.__ss.__r[1]; + stretSelRegister = (void *)registers.__ss.__r[2]; +#elif CLS_CPU_ARM64 + pc = FIRCLSThreadContextGetPC(®isters); + selRegister = (void *)registers.__ss.__x[1]; +#elif CLS_CPU_I386 + pc = registers.__ss.__eip; + selRegister = (void *)registers.__ss.__ecx; + stretSelRegister = (void *)registers.__ss.__ecx; +#elif CLS_CPU_X86_64 + pc = registers.__ss.__rip; + selRegister = (void *)registers.__ss.__rsi; + stretSelRegister = (void *)registers.__ss.__rdx; +#endif + + if ((pc >= OBJC_MSG_SEND_START) && (pc <= OBJC_MSG_SEND_END)) { + selectorAddress = selRegister; + } + +#if !CLS_CPU_ARM64 + if ((pc >= OBJC_MSG_SEND_SUPER_START) && (pc <= OBJC_MSG_SEND_SUPER_END)) { + selectorAddress = selRegister; + } + + if ((pc >= OBJC_MSG_SEND_STRET_START) && (pc <= OBJC_MSG_SEND_STRET_END)) { + selectorAddress = stretSelRegister; + } + + if ((pc >= OBJC_MSG_SEND_SUPER_STRET_START) && (pc <= OBJC_MSG_SEND_SUPER_STRET_END)) { + selectorAddress = stretSelRegister; + } + +#if CLS_CPU_X86 + if ((pc >= OBJC_MSG_SEND_FPRET_START) && (pc <= OBJC_MSG_SEND_FPRET_END)) { + selectorAddress = selRegister; + } +#endif +#endif + + if (!selectorAddress) { + return ""; + } + + if (!FIRCLSReadString((vm_address_t)selectorAddress, (char **)&selectorAddress, 128)) { + FIRCLSSDKLog("Unable to read the selector string\n"); + return ""; + } + + return selectorAddress; +} + +#define CRASH_ALIGN __attribute__((aligned(8))) +typedef struct { + unsigned version CRASH_ALIGN; + const char *message CRASH_ALIGN; + const char *signature CRASH_ALIGN; + const char *backtrace CRASH_ALIGN; + const char *message2 CRASH_ALIGN; + void *reserved CRASH_ALIGN; + void *reserved2 CRASH_ALIGN; +} crash_info_t; + +static void FIRCLSProcessRecordCrashInfo(FIRCLSFile *file) { + // TODO: this should be abstracted into binary images, if possible + FIRCLSBinaryImageRuntimeNode *nodes = _firclsContext.writable->binaryImage.nodes; + if (!nodes) { + FIRCLSSDKLogError("The node structure is NULL\n"); + return; + } + + for (uint32_t i = 0; i < CLS_BINARY_IMAGE_RUNTIME_NODE_COUNT; ++i) { + FIRCLSBinaryImageRuntimeNode *node = &nodes[i]; + + if (!node->crashInfo) { + continue; + } + + crash_info_t info; + + if (!FIRCLSReadMemory((vm_address_t)node->crashInfo, &info, sizeof(crash_info_t))) { + continue; + } + + FIRCLSSDKLogDebug("Found crash info with version %d\n", info.version); + + // Currently support versions 0 through 5. + // 4 was in use for a long time, but it appears that with iOS 9 / swift 2.0, the verison has + // been bumped. + if (info.version > 5) { + continue; + } + + if (!info.message) { + continue; + } + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + FIRCLSSDKLogInfo("Found crash info for %s\n", node->name); +#endif + + FIRCLSSDKLogDebug("attempting to read crash info string\n"); + + char *string = NULL; + + if (!FIRCLSReadString((vm_address_t)info.message, &string, 256)) { + FIRCLSSDKLogError("Failed to copy crash info string\n"); + continue; + } + + FIRCLSFileWriteArrayEntryHexEncodedString(file, string); + } +} + +void FIRCLSProcessRecordRuntimeInfo(FIRCLSProcess *process, FIRCLSFile *file) { + FIRCLSThreadContext mcontext; + + if (!FIRCLSProcessGetThreadState(process, process->crashedThread, &mcontext)) { + FIRCLSSDKLogError("unable to get crashed thread state"); + } + + FIRCLSFileWriteSectionStart(file, "runtime"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "objc_selector", FIRCLSProcessGetObjCSelectorName(mcontext)); + + FIRCLSFileWriteHashKey(file, "crash_info_entries"); + + FIRCLSFileWriteArrayStart(file); + FIRCLSProcessRecordCrashInfo(file); + FIRCLSFileWriteArrayEnd(file); + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h new file mode 100644 index 00000000..34a3e4fb --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSProcess.h @@ -0,0 +1,45 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <mach/mach.h> +#include <stdbool.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +typedef struct { + // task info + mach_port_t task; + + // thread stuff + thread_t thisThread; + thread_t crashedThread; + thread_act_array_t threads; + mach_msg_type_number_t threadCount; + void *uapVoid; // current thread state +} FIRCLSProcess; + +bool FIRCLSProcessInit(FIRCLSProcess *process, thread_t crashedThread, void *uapVoid); +bool FIRCLSProcessDestroy(FIRCLSProcess *process); +bool FIRCLSProcessDebuggerAttached(void); + +bool FIRCLSProcessSuspendAllOtherThreads(FIRCLSProcess *process); +bool FIRCLSProcessResumeAllOtherThreads(FIRCLSProcess *process); + +void FIRCLSProcessRecordThreadNames(FIRCLSProcess *process, FIRCLSFile *file); +void FIRCLSProcessRecordDispatchQueueNames(FIRCLSProcess *process, FIRCLSFile *file); +bool FIRCLSProcessRecordAllThreads(FIRCLSProcess *process, FIRCLSFile *file); +void FIRCLSProcessRecordStats(FIRCLSProcess *process, FIRCLSFile *file); +void FIRCLSProcessRecordRuntimeInfo(FIRCLSProcess *process, FIRCLSFile *file); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h new file mode 100644 index 00000000..982b3506 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h @@ -0,0 +1,101 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +__BEGIN_DECLS + +#ifdef __OBJC__ +extern NSString* const FIRCLSStartTimeKey; +extern NSString* const FIRCLSFirstRunloopTurnTimeKey; +extern NSString* const FIRCLSInBackgroundKey; +#if TARGET_OS_IPHONE +extern NSString* const FIRCLSDeviceOrientationKey; +extern NSString* const FIRCLSUIOrientationKey; +#endif +extern NSString* const FIRCLSUserIdentifierKey; +extern NSString* const FIRCLSUserNameKey; +extern NSString* const FIRCLSUserEmailKey; +extern NSString* const FIRCLSDevelopmentPlatformNameKey; +extern NSString* const FIRCLSDevelopmentPlatformVersionKey; +#endif + +extern const uint32_t FIRCLSUserLoggingMaxKVEntries; + +typedef struct { + const char* incrementalPath; + const char* compactedPath; + + uint32_t maxIncrementalCount; + uint32_t maxCount; +} FIRCLSUserLoggingKVStorage; + +typedef struct { + const char* aPath; + const char* bPath; + uint32_t maxSize; + uint32_t maxEntries; + bool restrictBySize; + uint32_t* entryCount; +} FIRCLSUserLoggingABStorage; + +typedef struct { + FIRCLSUserLoggingKVStorage userKVStorage; + FIRCLSUserLoggingKVStorage internalKVStorage; + + FIRCLSUserLoggingABStorage logStorage; + FIRCLSUserLoggingABStorage errorStorage; + FIRCLSUserLoggingABStorage customExceptionStorage; +} FIRCLSUserLoggingReadOnlyContext; + +typedef struct { + const char* activeUserLogPath; + const char* activeErrorLogPath; + const char* activeCustomExceptionPath; + uint32_t userKVCount; + uint32_t internalKVCount; + uint32_t errorsCount; +} FIRCLSUserLoggingWritableContext; + +void FIRCLSUserLoggingInit(FIRCLSUserLoggingReadOnlyContext* roContext, + FIRCLSUserLoggingWritableContext* rwContext); + +#ifdef __OBJC__ +void FIRCLSUserLoggingRecordUserKeyValue(NSString* key, id value); +void FIRCLSUserLoggingRecordInternalKeyValue(NSString* key, id value); +void FIRCLSUserLoggingWriteInternalKeyValue(NSString* key, NSString* value); + +void FIRCLSUserLoggingRecordError(NSError* error, NSDictionary<NSString*, id>* additionalUserInfo); + +NSDictionary* FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage* storage, + bool decodeHex); +void FIRCLSUserLoggingCompactKVEntries(FIRCLSUserLoggingKVStorage* storage); + +void FIRCLSUserLoggingRecordKeyValue(NSString* key, + id value, + FIRCLSUserLoggingKVStorage* storage, + uint32_t* counter); + +void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage* storage, + const char** activePath, + void (^openedFileBlock)(FIRCLSFile* file)); + +NSArray* FIRCLSUserLoggingStoredKeyValues(const char* path); + +OBJC_EXTERN void FIRCLSLog(NSString* format, ...) NS_FORMAT_FUNCTION(1, 2); +#endif + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m new file mode 100644 index 00000000..de4e6feb --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Components/FIRCLSUserLogging.m @@ -0,0 +1,523 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" + +#include <sys/time.h> + +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h" + +NSString *const FIRCLSStartTimeKey = @"com.crashlytics.kit-start-time"; +NSString *const FIRCLSFirstRunloopTurnTimeKey = @"com.crashlytics.first-run-loop-time"; +NSString *const FIRCLSInBackgroundKey = @"com.crashlytics.in-background"; +#if TARGET_OS_IPHONE +NSString *const FIRCLSDeviceOrientationKey = @"com.crashlytics.device-orientation"; +NSString *const FIRCLSUIOrientationKey = @"com.crashlytics.ui-orientation"; +#endif +NSString *const FIRCLSUserIdentifierKey = @"com.crashlytics.user-id"; +NSString *const FIRCLSDevelopmentPlatformNameKey = @"com.crashlytics.development-platform-name"; +NSString *const FIRCLSDevelopmentPlatformVersionKey = + @"com.crashlytics.development-platform-version"; + +const uint32_t FIRCLSUserLoggingMaxKVEntries = 64; + +#pragma mark - Prototypes +static void FIRCLSUserLoggingWriteKeyValue(NSString *key, + NSString *value, + FIRCLSUserLoggingKVStorage *storage, + uint32_t *counter); +static void FIRCLSUserLoggingCheckAndSwapABFiles(FIRCLSUserLoggingABStorage *storage, + const char **activePath, + off_t fileSize); +void FIRCLSLogInternal(NSString *message); + +#pragma mark - Setup +void FIRCLSUserLoggingInit(FIRCLSUserLoggingReadOnlyContext *roContext, + FIRCLSUserLoggingWritableContext *rwContext) { + rwContext->activeUserLogPath = roContext->logStorage.aPath; + rwContext->activeErrorLogPath = roContext->errorStorage.aPath; + rwContext->activeCustomExceptionPath = roContext->customExceptionStorage.aPath; + + rwContext->userKVCount = 0; + rwContext->internalKVCount = 0; + rwContext->errorsCount = 0; + + roContext->userKVStorage.maxIncrementalCount = FIRCLSUserLoggingMaxKVEntries; + roContext->internalKVStorage.maxIncrementalCount = roContext->userKVStorage.maxIncrementalCount; +} + +#pragma mark - KV Logging +void FIRCLSUserLoggingRecordInternalKeyValue(NSString *key, id value) { + FIRCLSUserLoggingRecordKeyValue(key, value, &_firclsContext.readonly->logging.internalKVStorage, + &_firclsContext.writable->logging.internalKVCount); +} + +void FIRCLSUserLoggingWriteInternalKeyValue(NSString *key, NSString *value) { + // Unsynchronized - must be run on the correct queue + FIRCLSUserLoggingWriteKeyValue(key, value, &_firclsContext.readonly->logging.internalKVStorage, + &_firclsContext.writable->logging.internalKVCount); +} + +void FIRCLSUserLoggingRecordUserKeyValue(NSString *key, id value) { + FIRCLSUserLoggingRecordKeyValue(key, value, &_firclsContext.readonly->logging.userKVStorage, + &_firclsContext.writable->logging.userKVCount); +} + +static id FIRCLSUserLoggingGetComponent(NSDictionary *entry, + NSString *componentName, + bool decodeHex) { + id value = [entry objectForKey:componentName]; + + return (decodeHex && value != [NSNull null]) ? FIRCLSFileHexDecodeString([value UTF8String]) + : value; +} + +static NSString *FIRCLSUserLoggingGetKey(NSDictionary *entry, bool decodeHex) { + return FIRCLSUserLoggingGetComponent(entry, @"key", decodeHex); +} + +static id FIRCLSUserLoggingGetValue(NSDictionary *entry, bool decodeHex) { + return FIRCLSUserLoggingGetComponent(entry, @"value", decodeHex); +} + +NSDictionary *FIRCLSUserLoggingGetCompactedKVEntries(FIRCLSUserLoggingKVStorage *storage, + bool decodeHex) { + if (!FIRCLSIsValidPointer(storage)) { + FIRCLSSDKLogError("storage invalid\n"); + return nil; + } + + NSArray *incrementalKVs = FIRCLSUserLoggingStoredKeyValues(storage->incrementalPath); + NSArray *compactedKVs = FIRCLSUserLoggingStoredKeyValues(storage->compactedPath); + + NSMutableDictionary *finalKVSet = [NSMutableDictionary new]; + + // These should all be unique, so there might be a more efficient way to + // do this + for (NSDictionary *entry in compactedKVs) { + NSString *key = FIRCLSUserLoggingGetKey(entry, decodeHex); + NSString *value = FIRCLSUserLoggingGetValue(entry, decodeHex); + + if (!key || !value) { + FIRCLSSDKLogError("compacted key/value contains a nil and must be dropped\n"); + continue; + } + + [finalKVSet setObject:value forKey:key]; + } + + // Now, assign the incremental values, in file order, so we overwrite any older values. + for (NSDictionary *entry in incrementalKVs) { + NSString *key = FIRCLSUserLoggingGetKey(entry, decodeHex); + NSString *value = FIRCLSUserLoggingGetValue(entry, decodeHex); + + if (!key || !value) { + FIRCLSSDKLogError("incremental key/value contains a nil and must be dropped\n"); + continue; + } + + if ([value isEqual:[NSNull null]]) { + [finalKVSet removeObjectForKey:key]; + } else { + [finalKVSet setObject:value forKey:key]; + } + } + + return finalKVSet; +} + +void FIRCLSUserLoggingCompactKVEntries(FIRCLSUserLoggingKVStorage *storage) { + if (!FIRCLSIsValidPointer(storage)) { + FIRCLSSDKLogError("Error: storage invalid\n"); + return; + } + + NSDictionary *finalKVs = FIRCLSUserLoggingGetCompactedKVEntries(storage, false); + + if (unlink(storage->compactedPath) != 0) { + FIRCLSSDKLog("Error: Unable to remove compacted KV store before compaction %s\n", + strerror(errno)); + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, storage->compactedPath, true)) { + FIRCLSSDKLog("Error: Unable to open compacted k-v file\n"); + return; + } + + uint32_t maxCount = storage->maxCount; + if ([finalKVs count] > maxCount) { + // We need to remove keys, to avoid going over the max. + // This is just about the worst way to go about doing this. There are lots of smarter ways, + // but it's very uncommon to go down this path. + NSArray *keys = [finalKVs allKeys]; + + FIRCLSSDKLogInfo("Truncating KV set, which is above max %d\n", maxCount); + + finalKVs = + [finalKVs dictionaryWithValuesForKeys:[keys subarrayWithRange:NSMakeRange(0, maxCount)]]; + } + + for (NSString *key in finalKVs) { + NSString *value = [finalKVs objectForKey:key]; + + FIRCLSFileWriteSectionStart(&file, "kv"); + FIRCLSFileWriteHashStart(&file); + // tricky - the values stored incrementally have already been hex-encoded + FIRCLSFileWriteHashEntryString(&file, "key", [key UTF8String]); + FIRCLSFileWriteHashEntryString(&file, "value", [value UTF8String]); + FIRCLSFileWriteHashEnd(&file); + FIRCLSFileWriteSectionEnd(&file); + } + + FIRCLSFileClose(&file); + + if (unlink(storage->incrementalPath) != 0) { + FIRCLSSDKLog("Error: Unable to remove incremental KV store after compaction %s\n", + strerror(errno)); + } +} + +void FIRCLSUserLoggingRecordKeyValue(NSString *key, + id value, + FIRCLSUserLoggingKVStorage *storage, + uint32_t *counter) { + if (!FIRCLSIsValidPointer(key)) { + FIRCLSSDKLogWarn("User provided bad key\n"); + return; + } + + // ensure that any invalid pointer is actually set to nil + if (!FIRCLSIsValidPointer(value) && value != nil) { + FIRCLSSDKLogWarn("Bad value pointer being clamped to nil\n"); + value = nil; + } + + if (!FIRCLSContextIsInitialized()) { + return; + } + + if ([value respondsToSelector:@selector(description)]) { + value = [value description]; + } else { + // passing nil will result in a JSON null being written, which is deserialized as [NSNull null], + // signaling to remove the key during compaction + value = nil; + } + + dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteKeyValue(key, value, storage, counter); + }); +} + +static void FIRCLSUserLoggingWriteKeyValue(NSString *key, + NSString *value, + FIRCLSUserLoggingKVStorage *storage, + uint32_t *counter) { + FIRCLSFile file; + + if (!FIRCLSIsValidPointer(storage) || !FIRCLSIsValidPointer(counter)) { + FIRCLSSDKLogError("Bad parameters\n"); + return; + } + + if (!FIRCLSFileInitWithPath(&file, storage->incrementalPath, true)) { + FIRCLSSDKLogError("Unable to open k-v file\n"); + return; + } + + FIRCLSFileWriteSectionStart(&file, "kv"); + FIRCLSFileWriteHashStart(&file); + FIRCLSFileWriteHashEntryHexEncodedString(&file, "key", [key UTF8String]); + FIRCLSFileWriteHashEntryHexEncodedString(&file, "value", [value UTF8String]); + FIRCLSFileWriteHashEnd(&file); + FIRCLSFileWriteSectionEnd(&file); + + FIRCLSFileClose(&file); + + *counter += 1; + if (*counter >= storage->maxIncrementalCount) { + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingCompactKVEntries(storage); + *counter = 0; + }); + } +} + +NSArray *FIRCLSUserLoggingStoredKeyValues(const char *path) { + if (!FIRCLSContextIsInitialized()) { + return nil; + } + + return FIRCLSFileReadSections(path, true, ^NSObject *(id obj) { + return [obj objectForKey:@"kv"]; + }); +} + +#pragma mark - NSError Logging +static void FIRCLSUserLoggingRecordErrorUserInfo(FIRCLSFile *file, + const char *fileKey, + NSDictionary<NSString *, id> *userInfo) { + if ([userInfo count] == 0) { + return; + } + + FIRCLSFileWriteHashKey(file, fileKey); + FIRCLSFileWriteArrayStart(file); + + for (id key in userInfo) { + id value = [userInfo objectForKey:key]; + if (![value respondsToSelector:@selector(description)]) { + continue; + } + + FIRCLSFileWriteArrayStart(file); + FIRCLSFileWriteArrayEntryHexEncodedString(file, [key UTF8String]); + FIRCLSFileWriteArrayEntryHexEncodedString(file, [[value description] UTF8String]); + FIRCLSFileWriteArrayEnd(file); + } + + FIRCLSFileWriteArrayEnd(file); +} + +static void FIRCLSUserLoggingWriteError(FIRCLSFile *file, + NSError *error, + NSDictionary<NSString *, id> *additionalUserInfo, + NSArray *addresses, + uint64_t timestamp) { + FIRCLSFileWriteSectionStart(file, "error"); + FIRCLSFileWriteHashStart(file); + FIRCLSFileWriteHashEntryHexEncodedString(file, "domain", [[error domain] UTF8String]); + FIRCLSFileWriteHashEntryInt64(file, "code", [error code]); + FIRCLSFileWriteHashEntryUint64(file, "time", timestamp); + + // addresses + FIRCLSFileWriteHashKey(file, "stacktrace"); + FIRCLSFileWriteArrayStart(file); + for (NSNumber *address in addresses) { + FIRCLSFileWriteArrayEntryUint64(file, [address unsignedLongLongValue]); + } + FIRCLSFileWriteArrayEnd(file); + + // user-info + FIRCLSUserLoggingRecordErrorUserInfo(file, "info", [error userInfo]); + FIRCLSUserLoggingRecordErrorUserInfo(file, "extra_info", additionalUserInfo); + + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSUserLoggingRecordError(NSError *error, + NSDictionary<NSString *, id> *additionalUserInfo) { + if (!error) { + return; + } + + if (!FIRCLSContextIsInitialized()) { + return; + } + + // record the stacktrace and timestamp here, so we + // are as close as possible to the user's log statement + NSArray *addresses = [NSThread callStackReturnAddresses]; + uint64_t timestamp = time(NULL); + + FIRCLSUserLoggingWriteAndCheckABFiles( + &_firclsContext.readonly->logging.errorStorage, + &_firclsContext.writable->logging.activeErrorLogPath, ^(FIRCLSFile *file) { + FIRCLSUserLoggingWriteError(file, error, additionalUserInfo, addresses, timestamp); + }); +} + +#pragma mark - CLSLog Support +void FIRCLSLog(NSString *format, ...) { + // If the format is nil do nothing just like NSLog. + if (!format) { + return; + } + + va_list args; + va_start(args, format); + NSString *msg = [[NSString alloc] initWithFormat:format arguments:args]; + va_end(args); + + FIRCLSLogInternal(msg); +} + +#pragma mark - Properties +uint32_t FIRCLSUserLoggingMaxLogSize(void) { + // don't forget that the message encoding overhead is 2x, and we + // wrap everything in a json structure with time. So, there is + // quite a penalty + + uint32_t size = 1024 * 64; + + return size * 2; +} + +uint32_t FIRCLSUserLoggingMaxErrorSize(void) { + return FIRCLSUserLoggingMaxLogSize(); +} + +#pragma mark - AB Logging +void FIRCLSUserLoggingCheckAndSwapABFiles(FIRCLSUserLoggingABStorage *storage, + const char **activePath, + off_t fileSize) { + if (!activePath || !storage) { + return; + } + + if (!*activePath) { + return; + } + + if (storage->restrictBySize) { + if (fileSize <= storage->maxSize) { + return; + } + } else { + if (!FIRCLSIsValidPointer(storage->entryCount)) { + FIRCLSSDKLogError("Error: storage has invalid pointer, but is restricted by entry count\n"); + return; + } + + if (*storage->entryCount < storage->maxEntries) { + return; + } + + // Here we have rolled over, so we have to reset our counter. + *storage->entryCount = 0; + } + + // if it is too big: + // - reset the other log + // - make it active + const char *otherPath = NULL; + + if (*activePath == storage->aPath) { + otherPath = storage->bPath; + } else { + // take this path if the pointer is invalid as well, to reset + otherPath = storage->aPath; + } + + // guard here against path being nil or empty + NSString *pathString = [NSString stringWithUTF8String:otherPath]; + + if ([pathString length] > 0) { + // ignore the error, because there is nothing we can do to recover here, and its likely + // any failures would be intermittent + + [[NSFileManager defaultManager] removeItemAtPath:pathString error:nil]; + } + + *activePath = otherPath; +} + +void FIRCLSUserLoggingWriteAndCheckABFiles(FIRCLSUserLoggingABStorage *storage, + const char **activePath, + void (^openedFileBlock)(FIRCLSFile *file)) { + if (!storage || !activePath || !openedFileBlock) { + return; + } + + if (!*activePath) { + return; + } + + if (storage->restrictBySize) { + if (storage->maxSize == 0) { + return; + } + } else { + if (storage->maxEntries == 0) { + return; + } + } + + dispatch_sync(FIRCLSGetLoggingQueue(), ^{ + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, *activePath, true)) { + FIRCLSSDKLog("Unable to open log file\n"); + return; + } + + openedFileBlock(&file); + + off_t fileSize = 0; + FIRCLSFileCloseWithOffset(&file, &fileSize); + + // increment the count before calling FIRCLSUserLoggingCheckAndSwapABFiles, so the value + // reflects the actual amount of stuff written + if (!storage->restrictBySize && FIRCLSIsValidPointer(storage->entryCount)) { + *storage->entryCount += 1; + } + + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingCheckAndSwapABFiles(storage, activePath, fileSize); + }); + }); +} + +void FIRCLSLogInternalWrite(FIRCLSFile *file, NSString *message, uint64_t time) { + FIRCLSFileWriteSectionStart(file, "log"); + FIRCLSFileWriteHashStart(file); + FIRCLSFileWriteHashEntryHexEncodedString(file, "msg", [message UTF8String]); + FIRCLSFileWriteHashEntryUint64(file, "time", time); + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSLogInternal(NSString *message) { + if (!message) { + return; + } + + if (!FIRCLSContextIsInitialized()) { + FIRCLSWarningLog(@"WARNING: FIRCLSLog has been used before (or concurrently with) " + @"Crashlytics initialization and cannot be recorded. The message was: \n%@", + message); + return; + } + struct timeval te; + + NSUInteger messageLength = [message length]; + int maxLogSize = _firclsContext.readonly->logging.logStorage.maxSize; + + if (messageLength > maxLogSize) { + FIRCLSWarningLog( + @"WARNING: Attempted to write %zd bytes, but %d is the maximum size of the log. " + @"Truncating to %d bytes.\n", + messageLength, maxLogSize, maxLogSize); + message = [message substringToIndex:maxLogSize]; + } + + // unable to get time - abort + if (gettimeofday(&te, NULL) != 0) { + return; + } + + const uint64_t time = te.tv_sec * 1000LL + te.tv_usec / 1000; + + FIRCLSUserLoggingWriteAndCheckABFiles(&_firclsContext.readonly->logging.logStorage, + &_firclsContext.writable->logging.activeUserLogPath, + ^(FIRCLSFile *file) { + FIRCLSLogInternalWrite(file, message, time); + }); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h new file mode 100644 index 00000000..2c259c29 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +typedef NS_ENUM(NSInteger, FIRCLSNetworkClientErrorType) { + FIRCLSNetworkClientErrorTypeUnknown = -1, + FIRCLSNetworkClientErrorTypeFileUnreadable = -2 +}; + +extern NSString *const FIRCLSNetworkClientErrorDomain; + +@protocol FIRCLSNetworkClientDelegate; +@class FIRCLSDataCollectionToken; +@class FIRCLSFileManager; + +@interface FIRCLSNetworkClient : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithQueue:(NSOperationQueue *)queue + fileManager:(FIRCLSFileManager *)fileManager + delegate:(id<FIRCLSNetworkClientDelegate>)delegate; + +@property(nonatomic, weak) id<FIRCLSNetworkClientDelegate> delegate; + +@property(nonatomic, readonly) NSOperationQueue *operationQueue; +@property(nonatomic, readonly) BOOL supportsBackgroundRequests; + +- (void)startUploadRequest:(NSURLRequest *)request + filePath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + immediately:(BOOL)immediate; + +- (void)attemptToReconnectBackgroundSessionWithCompletionBlock:(void (^)(void))completionBlock; + +@end + +@class FIRCLSNetworkClient; + +@protocol FIRCLSNetworkClientDelegate <NSObject> +@required +- (BOOL)networkClientCanUseBackgroundSessions:(FIRCLSNetworkClient *)client; + +@optional +- (void)networkClient:(FIRCLSNetworkClient *)client + didFinishUploadWithPath:(NSString *)path + error:(NSError *)error; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m new file mode 100644 index 00000000..b2dc34c4 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.m @@ -0,0 +1,366 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +NSString *const FIRCLSNetworkClientErrorDomain = @"FIRCLSNetworkError"; + +NSString *const FIRCLSNetworkClientBackgroundIdentifierSuffix = @".crash.background-session"; + +@interface FIRCLSNetworkClient () <NSURLSessionDelegate> { + NSURLSession *_session; +} + +@property(nonatomic, strong) void (^backgroundCompletionHandler)(void); +@property(nonatomic, strong, readonly) NSURLSession *session; +@property(nonatomic, assign) BOOL canUseBackgroundSession; +@property(nonatomic, strong) FIRCLSFileManager *fileManager; + +@end + +@implementation FIRCLSNetworkClient + +- (instancetype)initWithQueue:(NSOperationQueue *)queue + fileManager:(FIRCLSFileManager *)fileManager + delegate:(id<FIRCLSNetworkClientDelegate>)delegate { + self = [super init]; + if (!self) { + return nil; + } + + _operationQueue = queue; + _delegate = delegate; + _fileManager = fileManager; + + self.canUseBackgroundSession = [_delegate networkClientCanUseBackgroundSessions:self]; + + if (!self.supportsBackgroundRequests) { + FIRCLSDeveloperLog( + "Crashlytics:Crash:Client", + @"Background session uploading not supported, asynchronous uploading will be used"); + } + + return self; +} + +#pragma mark - Background Support +- (NSURLSession *)session { + // Creating a NSURLSession takes some time. Doing it lazily saves us time in the normal case. + if (_session) { + return _session; + } + + NSURLSessionConfiguration *config = nil; + + Class urlSessionClass; + Class urlSessionConfigurationClass; +#if FIRCLSURLSESSION_REQUIRED + urlSessionClass = [FIRCLSURLSession class]; + urlSessionConfigurationClass = [FIRCLSURLSessionConfiguration class]; +#else + urlSessionClass = [NSURLSession class]; + urlSessionConfigurationClass = [NSURLSessionConfiguration class]; +#endif + + if (self.supportsBackgroundRequests) { + NSString *sdkBundleID = FIRCLSApplicationGetSDKBundleID(); + NSString *backgroundConfigName = + [sdkBundleID stringByAppendingString:FIRCLSNetworkClientBackgroundIdentifierSuffix]; + + config = [urlSessionConfigurationClass backgroundSessionConfiguration:backgroundConfigName]; +#if TARGET_OS_IPHONE + [config setSessionSendsLaunchEvents:NO]; +#endif + } + + if (!config) { + // take this code path if we don't support background requests OR if we failed to create a + // background configuration + config = [urlSessionConfigurationClass defaultSessionConfiguration]; + } + + _session = [urlSessionClass sessionWithConfiguration:config + delegate:self + delegateQueue:self.operationQueue]; + + if (!_session || !config) { + FIRCLSErrorLog(@"Failed to initialize"); + } + + return _session; +} + +#if FIRCLSURLSESSION_REQUIRED +- (BOOL)NSURLSessionAvailable { + if ([[FIRCLSURLSession class] respondsToSelector:@selector(NSURLSessionShouldBeUsed)]) { + return [FIRCLSURLSession NSURLSessionShouldBeUsed]; + } + + return NSClassFromString(@"NSURLSession") != nil; +} +#endif + +- (BOOL)supportsBackgroundRequests { + return !FIRCLSApplicationIsExtension() +#if FIRCLSURLSESSION_REQUIRED + && [self NSURLSessionAvailable] +#endif + && self.canUseBackgroundSession; +} + +- (void)attemptToReconnectBackgroundSessionWithCompletionBlock:(void (^)(void))completionBlock { + if (!self.supportsBackgroundRequests) { + if (completionBlock) { + completionBlock(); + } + return; + } + + // This is the absolute minimum necessary. Perhaps we can do better? + if (completionBlock) { + [[NSOperationQueue mainQueue] addOperationWithBlock:completionBlock]; + } +} + +#pragma mark - API +- (void)startUploadRequest:(NSURLRequest *)request + filePath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + immediately:(BOOL)immediate { + if (![dataCollectionToken isValid]) { + FIRCLSErrorLog(@"An upload was requested with an invalid data collection token."); + return; + } + + if (immediate) { + [self startImmediateUploadRequest:request filePath:path]; + return; + } + + NSString *description = [self relativeTaskPathForAbsolutePath:path]; + [self checkForExistingTaskMatchingDescription:description + completionBlock:^(BOOL found) { + if (found) { + FIRCLSDeveloperLog( + "Crashlytics:Crash:Client", + @"A task currently exists for this upload, skipping"); + return; + } + + [self startNewUploadRequest:request filePath:path]; + }]; +} + +#pragma mark - Support API +- (void)startImmediateUploadRequest:(NSURLRequest *)request filePath:(NSString *)path { + // check the ivar directly, to avoid going back to the delegate + if (self.supportsBackgroundRequests) { + // this can be done here, because the request will be started synchronously. + [self startNewUploadRequest:request filePath:path]; + return; + } + + if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) { + FIRCLSSDKLog("Error: file unreadable\n"); + // Following the same logic as below, do not try to inform the delegate + return; + } + + NSMutableURLRequest *mutableRequest = [request mutableCopy]; + + [mutableRequest setHTTPBodyStream:[NSInputStream inputStreamWithFileAtPath:path]]; + + NSURLResponse *requestResponse = nil; + + [[NSURLSession sharedSession] + dataTaskWithRequest:mutableRequest + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + [FIRCLSNetworkResponseHandler + clientResponseType:requestResponse + handler:^(FIRCLSNetworkClientResponseType type, NSInteger statusCode) { + if (type != FIRCLSNetworkClientResponseSuccess) { + // don't even inform the delegate of a failure here, because we don't + // want any action to be taken synchronously + return; + } + + [[self delegate] networkClient:self + didFinishUploadWithPath:path + error:error]; + }]; + }]; +} + +- (void)startNewUploadRequest:(NSURLRequest *)request filePath:(NSString *)path { + if (![[NSFileManager defaultManager] isReadableFileAtPath:path]) { + [self.operationQueue addOperationWithBlock:^{ + [self + handleTaskDescription:path + completedWithError:[NSError errorWithDomain:FIRCLSNetworkClientErrorDomain + code:FIRCLSNetworkClientErrorTypeFileUnreadable + userInfo:@{@"path" : path}]]; + }]; + + return; + } + + NSURLSessionUploadTask *task = [self.session uploadTaskWithRequest:request + fromFile:[NSURL fileURLWithPath:path]]; + + // set the description, so we can determine what file was successfully uploaded later on + [task setTaskDescription:[self relativeTaskPathForAbsolutePath:path]]; + + [task resume]; +} + +- (NSString *)rootPath { + return self.fileManager.rootPath; +} + +- (NSString *)absolutePathForRelativeTaskPath:(NSString *)path { + return [self.rootPath stringByAppendingPathComponent:path]; +} + +- (NSString *)relativeTaskPathForAbsolutePath:(NSString *)path { + // make sure this has a tailing slash, so the path looks relative + NSString *root = [self.rootPath stringByAppendingString:@"/"]; + + if (![path hasPrefix:root]) { + FIRCLSSDKLog("Error: path '%s' is not at the root '%s'", [path UTF8String], [root UTF8String]); + return nil; + } + + return [path stringByReplacingOccurrencesOfString:root withString:@""]; +} + +#pragma mark - Task Management +- (BOOL)taskArray:(NSArray *)array hasTaskMatchingDescription:(NSString *)description { + NSUInteger idx = [array indexOfObjectPassingTest:^BOOL(id obj, NSUInteger arrayIdx, BOOL *stop) { + return [[obj taskDescription] isEqualToString:description]; + }]; + + return idx != NSNotFound; +} + +- (void)checkSession:(NSURLSession *)session + forTasksMatchingDescription:(NSString *)description + completionBlock:(void (^)(BOOL found))block { + if (!session) { + block(NO); + return; + } + + [session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, + NSArray *downloadTasks) { + if ([self taskArray:uploadTasks hasTaskMatchingDescription:description]) { + block(YES); + return; + } + + if ([self taskArray:dataTasks hasTaskMatchingDescription:description]) { + block(YES); + return; + } + + if ([self taskArray:downloadTasks hasTaskMatchingDescription:description]) { + block(YES); + return; + } + + block(NO); + }]; +} + +- (void)checkForExistingTaskMatchingDescription:(NSString *)description + completionBlock:(void (^)(BOOL found))block { + // Do not instantiate the normal session, because if it doesn't exist yet, it cannot possibly have + // existing tasks + [_operationQueue addOperationWithBlock:^{ + [self checkSession:self.session + forTasksMatchingDescription:description + completionBlock:^(BOOL found) { + block(found); + }]; + }]; +} + +#pragma mark - Result Handling +// This method is duplicated from FIRCLSFABNetworkClient. Sharing it is a little weird - I didn't +// feel like it fit into FIRCLSNetworkResponseHandler. +- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response block:(void (^)(void))block { + NSTimeInterval delay = [FIRCLSNetworkResponseHandler retryValueForResponse:response]; + + // FIRCLSDeveloperLog("Network", @"Restarting request after %f", delay); + + FIRCLSAddOperationAfter(delay, _operationQueue, block); +} + +- (void)restartTask:(NSURLSessionTask *)task { + NSURLRequest *request = [task originalRequest]; + + [self runAfterRetryValueFromResponse:[task response] + block:^{ + NSString *path = [self + absolutePathForRelativeTaskPath:[task taskDescription]]; + + [self startNewUploadRequest:request filePath:path]; + }]; +} + +- (void)handleTask:(NSURLSessionTask *)task completedWithError:(NSError *)error { + [self handleTaskDescription:[task taskDescription] completedWithError:error]; +} + +- (void)handleTaskDescription:(NSString *)taskDescription completedWithError:(NSError *)error { + NSString *path = [self absolutePathForRelativeTaskPath:taskDescription]; + + [[self delegate] networkClient:self didFinishUploadWithPath:path error:error]; +} + +#pragma mark - NSURLSessionDelegate +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { + FIRCLSDeveloperLog("Crashlytics:Crash:Client", @"session became invalid: %@", error); +} + +// Careful! Not implementing this method appears to cause a crash when using a background task +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task + didCompleteWithError:(NSError *)error { + [FIRCLSNetworkResponseHandler handleCompletedResponse:task.response + forOriginalRequest:task.originalRequest + error:error + block:^(BOOL restart, NSError *taskError) { + if (restart) { + [self restartTask:task]; + return; + } + + [self handleTask:task + completedWithError:taskError]; + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h new file mode 100644 index 00000000..2e3e0eea --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h @@ -0,0 +1,57 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h" +#include "Crashlytics/Crashlytics/Public/FIRCrashlytics.h" +#include "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" + +@class FBLPromise<T>; + +NS_ASSUME_NONNULL_BEGIN + +@class FIRCLSDataCollectionArbiter; +@class FIRCLSFileManager; +@class FIRCLSInternalReport; +@class FIRCLSSettings; +@class GDTCORTransport; +@class FIRInstallations; +@protocol FIRAnalyticsInterop; + +@interface FIRCLSReportManager : NSObject + +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + installations:(FIRInstallations *)installations + analytics:(nullable id<FIRAnalyticsInterop>)analytics + googleAppID:(NSString *)googleAppID + dataArbiter:(FIRCLSDataCollectionArbiter *)dataArbiter + googleTransport:(GDTCORTransport *)googleTransport + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +- (FBLPromise<NSNumber *> *)startWithProfilingMark:(FIRCLSProfileMark)mark; + +- (FBLPromise<NSNumber *> *)checkForUnsentReports; +- (FBLPromise *)sendUnsentReports; +- (FBLPromise *)deleteUnsentReports; + +@end + +extern NSString *const FIRCLSConfigSubmitReportsKey; +extern NSString *const FIRCLSConfigPackageReportsKey; + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m new file mode 100644 index 00000000..a5df5a65 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.m @@ -0,0 +1,909 @@ +// Copyright 2019 Google +// +// 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. + +// +// The report manager has the ability to send to two different endpoints. +// +// The old legacy flow for a report goes through the following states/folders: +// 1. active - .clsrecords optimized for crash time persistence +// 2. processing - .clsrecords with attempted symbolication +// 3. prepared-legacy - .multipartmime of compressed .clsrecords +// +// The new flow for a report goes through the following states/folders: +// 1. active - .clsrecords optimized for crash time persistence +// 2. processing - .clsrecords with attempted symbolication +// 3. prepared - .clsrecords moved from processing with no changes +// +// The code was designed so the report processing workflows are not dramatically different from one +// another. The design will help avoid having a lot of conditional code blocks throughout the +// codebase. +// + +#include <stdatomic.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h" +#import "Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h" +#import "Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h" + +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#import "Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h" +#import "Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h" +#import "Crashlytics/Shared/FIRCLSConstants.h" + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h" + +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" +#import "Interop/Analytics/Public/FIRAnalyticsInteropListener.h" + +#include "Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h" + +#if TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#else +#import <AppKit/AppKit.h> +#endif + +static NSTimeInterval const CLSReportRetryInterval = 10 * 60; + +static NSString *FIRCLSFirebaseAnalyticsEventLogFormat = @"$A$:%@"; + +@interface FIRCLSAnalyticsInteropListener : NSObject <FIRAnalyticsInteropListener> { +} +@end + +@implementation FIRCLSAnalyticsInteropListener + +- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters { + NSDictionary *event = @{ + @"name" : name, + @"parameters" : parameters, + }; + NSString *json = FIRCLSFIRAEventDictionaryToJSON(event); + if (json != nil) { + FIRCLSLog(FIRCLSFirebaseAnalyticsEventLogFormat, json); + } +} + +@end + +/** + * A FIRReportAction is used to indicate how to handle unsent reports. + */ +typedef NS_ENUM(NSInteger, FIRCLSReportAction) { + /** Upload the reports to Crashlytics. */ + FIRCLSReportActionSend, + /** Delete the reports without uploading them. */ + FIRCLSReportActionDelete, +}; + +/** + * This is just a helper to make code using FIRReportAction more readable. + */ +typedef NSNumber FIRCLSWrappedReportAction; +@implementation NSNumber (FIRCLSWrappedReportAction) +- (FIRCLSReportAction)reportActionValue { + return [self intValue]; +} +@end + +/** + * This is a helper to make code using NSNumber for bools more readable. + */ +typedef NSNumber FIRCLSWrappedBool; + +@interface FIRCLSReportManager () <FIRCLSNetworkClientDelegate, + FIRCLSReportUploaderDelegate, + FIRCLSReportUploaderDataSource> { + FIRCLSFileManager *_fileManager; + FIRCLSNetworkClient *_networkClient; + FIRCLSReportUploader *_uploader; + dispatch_queue_t _dispatchQueue; + NSOperationQueue *_operationQueue; + id<FIRAnalyticsInterop> _analytics; + + // A promise that will be resolved when unsent reports are found on the device, and + // processReports: can be called to decide how to deal with them. + FBLPromise<FIRCLSWrappedBool *> *_unsentReportsAvailable; + + // A promise that will be resolved when the user has provided an action that they want to perform + // for all the unsent reports. + FBLPromise<FIRCLSWrappedReportAction *> *_reportActionProvided; + + // A promise that will be resolved when all unsent reports have been "handled". They won't + // necessarily have been uploaded, but we will know whether they should be sent or deleted, and + // the initial work to make that happen will have been processed on the work queue. + // + // Currently only used for testing + FBLPromise *_unsentReportsHandled; + + // A token to make sure that checkForUnsentReports only gets called once. + atomic_bool _checkForUnsentReportsCalled; + + BOOL _registeredAnalyticsEventListener; +} + +@property(nonatomic, readonly) NSString *googleAppID; + +@property(nonatomic, strong) FIRCLSDataCollectionArbiter *dataArbiter; + +// Uniquely identifies a build / binary of the app +@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel; + +// Uniquely identifies an install of the app +@property(nonatomic, strong) FIRCLSInstallIdentifierModel *installIDModel; + +// Uniquely identifies a run of the app +@property(nonatomic, strong) FIRCLSExecutionIdentifierModel *executionIDModel; + +// Settings fetched from the server +@property(nonatomic, strong) FIRCLSSettings *settings; + +// Runs the operations that fetch settings and call onboarding endpoints +@property(nonatomic, strong) FIRCLSSettingsOnboardingManager *settingsAndOnboardingManager; + +@property(nonatomic, strong) GDTCORTransport *googleTransport; + +@end + +@implementation FIRCLSReportManager + +// Used only for internal data collection E2E testing +static void (^reportSentCallback)(void); + +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + installations:(FIRInstallations *)installations + analytics:(id<FIRAnalyticsInterop>)analytics + googleAppID:(NSString *)googleAppID + dataArbiter:(FIRCLSDataCollectionArbiter *)dataArbiter + googleTransport:(GDTCORTransport *)googleTransport + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + settings:(FIRCLSSettings *)settings { + self = [super init]; + if (!self) { + return nil; + } + + _fileManager = fileManager; + _analytics = analytics; + _googleAppID = [googleAppID copy]; + _dataArbiter = dataArbiter; + + _googleTransport = googleTransport; + + NSString *sdkBundleID = FIRCLSApplicationGetSDKBundleID(); + + _operationQueue = [NSOperationQueue new]; + [_operationQueue setMaxConcurrentOperationCount:1]; + [_operationQueue setName:[sdkBundleID stringByAppendingString:@".work-queue"]]; + + _dispatchQueue = dispatch_queue_create("com.google.firebase.crashlytics.startup", 0); + _operationQueue.underlyingQueue = _dispatchQueue; + + _networkClient = [self clientWithOperationQueue:_operationQueue]; + + _unsentReportsAvailable = [FBLPromise pendingPromise]; + _reportActionProvided = [FBLPromise pendingPromise]; + _unsentReportsHandled = [FBLPromise pendingPromise]; + + _checkForUnsentReportsCalled = NO; + + _installIDModel = [[FIRCLSInstallIdentifierModel alloc] initWithInstallations:installations]; + _executionIDModel = [[FIRCLSExecutionIdentifierModel alloc] init]; + + _settings = settings; + _appIDModel = appIDModel; + + _settingsAndOnboardingManager = + [[FIRCLSSettingsOnboardingManager alloc] initWithAppIDModel:appIDModel + installIDModel:self.installIDModel + settings:self.settings + fileManager:self.fileManager + googleAppID:self.googleAppID]; + + return self; +} + +- (FIRCLSNetworkClient *)clientWithOperationQueue:(NSOperationQueue *)queue { + return [[FIRCLSNetworkClient alloc] initWithQueue:queue fileManager:_fileManager delegate:self]; +} + +/** + * Returns the number of unsent reports on the device, including the ones passed in. + */ +- (int)unsentReportsCountWithPreexisting:(NSArray<NSString *> *)paths { + int count = [self countSubmittableAndDeleteUnsubmittableReportPaths:paths]; + + count += _fileManager.processingPathContents.count; + + if (self.settings.shouldUseNewReportEndpoint) { + count += _fileManager.preparedPathContents.count; + } else { + count += _fileManager.legacyPreparedPathContents.count; + } + return count; +} + +// This method returns a promise that is resolved with a wrapped FIRReportAction once the user has +// indicated whether they want to upload currently cached reports. +// This method should only be called when we have determined there is at least 1 unsent report. +// This method waits until either: +// 1. Data collection becomes enabled, in which case, the promise will be resolved with Send. +// 2. The developer uses the processCrashReports API to indicate whether the report +// should be sent or deleted, at which point the promise will be resolved with the action. +- (FBLPromise<FIRCLSWrappedReportAction *> *)waitForReportAction { + FIRCLSDebugLog(@"[Crashlytics:Crash] Notifying that unsent reports are available."); + [_unsentReportsAvailable fulfill:@YES]; + + // If data collection gets enabled while we are waiting for an action, go ahead and send the + // reports, and any subsequent explicit response will be ignored. + FBLPromise<FIRCLSWrappedReportAction *> *collectionEnabled = + [[self.dataArbiter waitForCrashlyticsCollectionEnabled] + then:^id _Nullable(NSNumber *_Nullable value) { + return @(FIRCLSReportActionSend); + }]; + + FIRCLSDebugLog(@"[Crashlytics:Crash] Waiting for send/deleteUnsentReports to be called."); + // Wait for either the processReports callback to be called, or data collection to be enabled. + return [FBLPromise race:@[ collectionEnabled, _reportActionProvided ]]; +} + +- (FBLPromise<FIRCLSWrappedBool *> *)checkForUnsentReports { + bool expectedCalled = NO; + if (!atomic_compare_exchange_strong(&_checkForUnsentReportsCalled, &expectedCalled, YES)) { + FIRCLSErrorLog(@"checkForUnsentReports should only be called once per execution."); + return [FBLPromise resolvedWith:@NO]; + } + return _unsentReportsAvailable; +} + +- (FBLPromise *)sendUnsentReports { + [_reportActionProvided fulfill:@(FIRCLSReportActionSend)]; + return _unsentReportsHandled; +} + +- (FBLPromise *)deleteUnsentReports { + [_reportActionProvided fulfill:@(FIRCLSReportActionDelete)]; + return _unsentReportsHandled; +} + +- (FBLPromise<NSNumber *> *)startWithProfilingMark:(FIRCLSProfileMark)mark { + NSString *executionIdentifier = self.executionIDModel.executionID; + + // This needs to be called before any values are read from settings + NSTimeInterval currentTimestamp = [NSDate timeIntervalSinceReferenceDate]; + [self.settings reloadFromCacheWithGoogleAppID:self.googleAppID currentTimestamp:currentTimestamp]; + + if (![self validateAppIdentifiers]) { + return [FBLPromise resolvedWith:@NO]; + } + +#if DEBUG + FIRCLSDebugLog(@"Root: %@", [_fileManager rootPath]); +#endif + + if ([self.dataArbiter isLegacyDataCollectionKeyInPlist]) { + FIRCLSErrorLog(@"Found legacy data collection key in app's Info.plist: " + @"firebase_crashlytics_collection_enabled"); + FIRCLSErrorLog(@"Please update your Info.plist to use the new data collection key: " + @"FirebaseCrashlyticsCollectionEnabled"); + FIRCLSErrorLog(@"The legacy data collection Info.plist value could be overridden by " + @"calling: [Fabric with:...]"); + FIRCLSErrorLog(@"The new value can be overridden by calling: [[FIRCrashlytics " + @"crashlytics] setCrashlyticsCollectionEnabled:<isEnabled>]"); + + return [FBLPromise resolvedWith:@NO]; + } + + if (![_fileManager createReportDirectories]) { + return [FBLPromise resolvedWith:@NO]; + } + + // Grab existing reports + BOOL launchFailure = [self checkForAndCreateLaunchMarker]; + NSArray *preexistingReportPaths = _fileManager.activePathContents; + + FIRCLSInternalReport *report = [self setupCurrentReport:executionIdentifier]; + if (!report) { + FIRCLSErrorLog(@"Unable to setup a new report"); + } + + if (![self startCrashReporterWithProfilingMark:mark report:report]) { + FIRCLSErrorLog(@"Unable to start crash reporter"); + report = nil; + } + + // Regenerate the Install ID on a background thread if it needs to rotate because + // fetching the Firebase Install ID can be slow on some devices. This should happen after we + // create the session on disk so that we can update the Install ID in the written crash report + // metadata. + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + [self checkAndRotateInstallUUIDIfNeededWithReport:report]; + }); + + FBLPromise<NSNumber *> *promise = [FBLPromise resolvedWith:@(report != nil)]; + + if ([self.dataArbiter isCrashlyticsCollectionEnabled]) { + FIRCLSDebugLog(@"Automatic data collection is enabled."); + FIRCLSDebugLog(@"Unsent reports will be uploaded at startup"); + FIRCLSDataCollectionToken *dataCollectionToken = [FIRCLSDataCollectionToken validToken]; + + [self beginSettingsAndOnboardingWithToken:dataCollectionToken waitForSettingsRequest:NO]; + + [self beginReportUploadsWithToken:dataCollectionToken + preexistingReportPaths:preexistingReportPaths + blockingSend:launchFailure + report:report]; + + // If data collection is enabled, the SDK will not notify the user + // when unsent reports are available, or respect Send / DeleteUnsentReports + [_unsentReportsAvailable fulfill:@NO]; + + } else { + FIRCLSDebugLog(@"Automatic data collection is disabled."); + + // TODO: This counting of the file system happens on the main thread. Now that some of the other + // work below has been made async and moved to the dispatch queue, maybe we can move this code + // to the dispatch queue as well. + int unsentReportsCount = [self unsentReportsCountWithPreexisting:preexistingReportPaths]; + if (unsentReportsCount > 0) { + FIRCLSDebugLog( + @"[Crashlytics:Crash] %d unsent reports are available. Checking for upload permission.", + unsentReportsCount); + // Wait for an action to get sent, either from processReports: or automatic data collection. + promise = [[self waitForReportAction] + onQueue:_dispatchQueue + then:^id _Nullable(FIRCLSWrappedReportAction *_Nullable wrappedAction) { + // Process the actions for the reports on disk. + FIRCLSReportAction action = [wrappedAction reportActionValue]; + if (action == FIRCLSReportActionSend) { + FIRCLSDebugLog(@"Sending unsent reports."); + FIRCLSDataCollectionToken *dataCollectionToken = + [FIRCLSDataCollectionToken validToken]; + + // For the new report endpoint, the orgID is not needed. + // For the legacy report endpoint, wait on settings if orgID is not available. + BOOL waitForSetting = + !self.settings.shouldUseNewReportEndpoint && !self.settings.orgID; + + [self beginSettingsAndOnboardingWithToken:dataCollectionToken + waitForSettingsRequest:waitForSetting]; + + [self beginReportUploadsWithToken:dataCollectionToken + preexistingReportPaths:preexistingReportPaths + blockingSend:NO + report:report]; + + } else if (action == FIRCLSReportActionDelete) { + FIRCLSDebugLog(@"Deleting unsent reports."); + [self deleteUnsentReportsWithPreexisting:preexistingReportPaths]; + } else { + FIRCLSErrorLog(@"Unknown report action: %d", action); + } + return @(report != nil); + }]; + } else { + FIRCLSDebugLog(@"[Crashlytics:Crash] There are no unsent reports."); + [_unsentReportsAvailable fulfill:@NO]; + } + } + + if (report != nil) { + // capture the start-up time here, but record it asynchronously + double endMark = FIRCLSProfileEnd(mark); + + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSStartTimeKey, [@(endMark) description]); + }); + } + + // To make the code more predictable and therefore testable, don't resolve the startup promise + // until the operations that got queued up for processing reports have been processed through the + // work queue. + NSOperationQueue *__weak queue = _operationQueue; + FBLPromise *__weak unsentReportsHandled = _unsentReportsHandled; + promise = [promise then:^id _Nullable(NSNumber *_Nullable value) { + [queue waitUntilAllOperationsAreFinished]; + // Signal that to callers of processReports that everything is finished. + [unsentReportsHandled fulfill:nil]; + return value; + }]; + + return promise; +} + +- (void)checkAndRotateInstallUUIDIfNeededWithReport:(FIRCLSInternalReport *)report { + [self.installIDModel regenerateInstallIDIfNeededWithBlock:^(BOOL didRotate) { + if (!didRotate) { + return; + } + + FIRCLSContextUpdateMetadata(report, self.settings, self.installIDModel, self->_fileManager); + }]; +} + +- (void)beginSettingsAndOnboardingWithToken:(FIRCLSDataCollectionToken *)token + waitForSettingsRequest:(BOOL)waitForSettings { + if (self.settings.isCacheExpired) { + // This method can be called more than once if the user calls + // SendUnsentReports again, so don't repeat the settings fetch + static dispatch_once_t settingsFetchOnceToken; + dispatch_once(&settingsFetchOnceToken, ^{ + [self.settingsAndOnboardingManager beginSettingsAndOnboardingWithGoogleAppId:self.googleAppID + token:token + waitForCompletion:waitForSettings]; + }); + } +} + +- (void)beginReportUploadsWithToken:(FIRCLSDataCollectionToken *)token + preexistingReportPaths:(NSArray *)preexistingReportPaths + blockingSend:(BOOL)blockingSend + report:(FIRCLSInternalReport *)report { + if (self.settings.collectReportsEnabled) { + [self processExistingReportPaths:preexistingReportPaths + dataCollectionToken:token + asUrgent:blockingSend]; + [self handleContentsInOtherReportingDirectoriesWithToken:token]; + + } else { + FIRCLSInfoLog(@"Collect crash reports is disabled"); + [self deleteUnsentReportsWithPreexisting:preexistingReportPaths]; + } +} + +- (BOOL)startCrashReporterWithProfilingMark:(FIRCLSProfileMark)mark + report:(FIRCLSInternalReport *)report { + if (!report) { + return NO; + } + + if (!FIRCLSContextInitialize(report, self.settings, self.installIDModel, _fileManager)) { + return NO; + } + + [self setupStateNotifications]; + + [self registerAnalyticsEventListener]; + + [self crashReportingSetupCompleted:mark]; + + return YES; +} + +- (void)crashReportingSetupCompleted:(FIRCLSProfileMark)mark { + // check our handlers + FIRCLSDispatchAfter(2.0, dispatch_get_main_queue(), ^{ + FIRCLSExceptionCheckHandlers((__bridge void *)(self)); + FIRCLSSignalCheckHandlers(); +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSMachExceptionCheckHandlers(); +#endif + }); + + // remove the launch failure marker and record the startup time + dispatch_async(dispatch_get_main_queue(), ^{ + [self removeLaunchFailureMarker]; + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSFirstRunloopTurnTimeKey, + [@(FIRCLSProfileEnd(mark)) description]); + }); + }); +} + +- (BOOL)validateAppIdentifiers { + // When the ApplicationIdentifierModel fails to initialize, it is usually due to + // failing computeExecutableInfo. This can happen if the user sets the + // Exported Symbols File in Build Settings, and leaves off the one symbol + // that Crashlytics needs, "__mh_execute_header" (wich is defined in mach-o/ldsyms.h as + // _MH_EXECUTE_SYM). From https://github.com/firebase/firebase-ios-sdk/issues/5020 + if (!self.appIDModel) { + FIRCLSErrorLog( + @"Crashlytics could not find the symbol for the app's main function and cannot " + @"start up. This can happen when Exported Symbols File is set in Build Settings. To " + @"resolve this, add \"__mh_execute_header\" as a newline to your Exported Symbols File."); + return NO; + } + + if (self.appIDModel.bundleID.length == 0) { + FIRCLSErrorLog(@"An application must have a valid bundle identifier in its Info.plist"); + return NO; + } + + return YES; +} + +- (FIRCLSReportUploader *)uploader { + if (!_uploader) { + _uploader = [[FIRCLSReportUploader alloc] initWithQueue:self.operationQueue + delegate:self + dataSource:self + client:self.networkClient + fileManager:_fileManager + analytics:_analytics]; + } + + return _uploader; +} + +#pragma mark - Reporting Lifecycle + +- (FIRCLSInternalReport *)setupCurrentReport:(NSString *)executionIdentifier { + [self createLaunchFailureMarker]; + + NSString *reportPath = [_fileManager setupNewPathForExecutionIdentifier:executionIdentifier]; + + return [[FIRCLSInternalReport alloc] initWithPath:reportPath + executionIdentifier:executionIdentifier]; +} + +- (int)countSubmittableAndDeleteUnsubmittableReportPaths:(NSArray *)reportPaths { + int count = 0; + for (NSString *path in reportPaths) { + FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path]; + if ([report needsToBeSubmitted]) { + count++; + } else { + [self.operationQueue addOperationWithBlock:^{ + [self->_fileManager removeItemAtPath:path]; + }]; + } + } + return count; +} + +- (void)processExistingReportPaths:(NSArray *)reportPaths + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent { + for (NSString *path in reportPaths) { + [self processExistingActiveReportPath:path + dataCollectionToken:dataCollectionToken + asUrgent:urgent]; + } +} + +- (void)processExistingActiveReportPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent { + FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path]; + + // TODO: needsToBeSubmitted should really be called on the background queue. + if (![report needsToBeSubmitted]) { + [self.operationQueue addOperationWithBlock:^{ + [self->_fileManager removeItemAtPath:path]; + }]; + + return; + } + + if (urgent && [dataCollectionToken isValid]) { + // We can proceed without the delegate. + [[self uploader] prepareAndSubmitReport:report + dataCollectionToken:dataCollectionToken + asUrgent:urgent + withProcessing:YES]; + return; + } + + [self submitReport:report dataCollectionToken:dataCollectionToken]; +} + +- (void)submitReport:(FIRCLSInternalReport *)report + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken { + [self.operationQueue addOperationWithBlock:^{ + [[self uploader] prepareAndSubmitReport:report + dataCollectionToken:dataCollectionToken + asUrgent:NO + withProcessing:YES]; + }]; + + [self didSubmitReport]; +} + +// This is the side-effect of calling deleteUnsentReports, or collect_reports setting +// being false +- (void)deleteUnsentReportsWithPreexisting:(NSArray *)preexistingReportPaths { + [self removeExistingReportPaths:preexistingReportPaths]; + + [self removeExistingReportPaths:self.fileManager.processingPathContents]; + if (self.settings.shouldUseNewReportEndpoint) { + [self removeExistingReportPaths:self.fileManager.preparedPathContents]; + } else { + [self removeExistingReportPaths:self.fileManager.legacyPreparedPathContents]; + } +} + +- (void)removeExistingReportPaths:(NSArray *)reportPaths { + [self.operationQueue addOperationWithBlock:^{ + for (NSString *path in reportPaths) { + [self.fileManager removeItemAtPath:path]; + } + }]; +} + +- (void)handleContentsInOtherReportingDirectoriesWithToken:(FIRCLSDataCollectionToken *)token { + [self handleExistingFilesInProcessingWithToken:token]; + [self handleExistingFilesInPreparedWithToken:token]; +} + +- (void)handleExistingFilesInProcessingWithToken:(FIRCLSDataCollectionToken *)token { + NSArray *processingPaths = _fileManager.processingPathContents; + + // deal with stuff in processing more carefully - do not process again + [self.operationQueue addOperationWithBlock:^{ + for (NSString *path in processingPaths) { + FIRCLSInternalReport *report = [FIRCLSInternalReport reportWithPath:path]; + [[self uploader] prepareAndSubmitReport:report + dataCollectionToken:token + asUrgent:NO + withProcessing:NO]; + } + }]; +} + +- (void)handleExistingFilesInPreparedWithToken:(FIRCLSDataCollectionToken *)token { + NSArray *preparedPaths = self.settings.shouldUseNewReportEndpoint + ? _fileManager.preparedPathContents + : _fileManager.legacyPreparedPathContents; + + // Give our network client a chance to reconnect here, if needed. This attempts to avoid + // trying to re-submit a prepared file that is already in flight. + [self.networkClient attemptToReconnectBackgroundSessionWithCompletionBlock:^{ + [self.operationQueue addOperationWithBlock:^{ + [self uploadPreexistingFiles:preparedPaths withToken:token]; + }]; + }]; +} + +- (void)uploadPreexistingFiles:(NSArray *)files withToken:(FIRCLSDataCollectionToken *)token { + // Because this could happen quite a bit after the inital set of files was + // captured, some could be completed (deleted). So, just double-check to make sure + // the file still exists. + + for (NSString *path in files) { + if (![[_fileManager underlyingFileManager] fileExistsAtPath:path]) { + continue; + } + + [[self uploader] uploadPackagedReportAtPath:path dataCollectionToken:token asUrgent:NO]; + } +} + +- (void)retryUploadForReportAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)token { + FIRCLSAddOperationAfter(CLSReportRetryInterval, self.operationQueue, ^{ + FIRCLSDeveloperLog("Crashlytics:Crash", @"re-attempting report submission"); + [[self uploader] uploadPackagedReportAtPath:path dataCollectionToken:token asUrgent:NO]; + }); +} + +#pragma mark - Launch Failure Detection +- (NSString *)launchFailureMarkerPath { + return [[_fileManager structurePath] stringByAppendingPathComponent:@"launchmarker"]; +} + +- (BOOL)createLaunchFailureMarker { + // It's tempting to use - [NSFileManger createFileAtPath:contents:attributes:] here. But that + // operation, even with empty/nil contents does a ton of work to write out nothing via a + // temporarly file. This is a much faster implemenation. + const char *path = [[self launchFailureMarkerPath] fileSystemRepresentation]; + +#if TARGET_OS_IPHONE + /* + * data-protected non-portable open(2) : + * int open_dprotected_np(user_addr_t path, int flags, int class, int dpflags, int mode) + */ + int fd = open_dprotected_np(path, O_WRONLY | O_CREAT | O_TRUNC, 4, 0, 0644); +#else + int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); +#endif + if (fd == -1) { + return NO; + } + + return close(fd) == 0; +} + +- (BOOL)launchFailureMarkerPresent { + return [[_fileManager underlyingFileManager] fileExistsAtPath:[self launchFailureMarkerPath]]; +} + +- (BOOL)removeLaunchFailureMarker { + return [_fileManager removeItemAtPath:[self launchFailureMarkerPath]]; +} + +- (BOOL)checkForAndCreateLaunchMarker { + BOOL launchFailure = [self launchFailureMarkerPresent]; + if (launchFailure) { + FIRCLSDeveloperLog("Crashlytics:Crash", + @"Last launch failed: this may indicate a crash shortly after app launch."); + } else { + [self createLaunchFailureMarker]; + } + + return launchFailure; +} + +#pragma mark - + +- (void)registerAnalyticsEventListener { + if (_registeredAnalyticsEventListener) { + return; + } + FIRCLSAnalyticsInteropListener *listener = [[FIRCLSAnalyticsInteropListener alloc] init]; + [FIRCLSFCRAnalytics registerEventListener:listener toAnalytics:_analytics]; + _registeredAnalyticsEventListener = YES; +} + +#pragma mark - Notifications +- (void)setupStateNotifications { + [self captureInitialNotificationStates]; + +#if TARGET_OS_IOS + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(willBecomeActive:) + name:UIApplicationWillEnterForegroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didBecomeInactive:) + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didChangeOrientation:) + name:UIDeviceOrientationDidChangeNotification + object:nil]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(didChangeUIOrientation:) + name:UIApplicationDidChangeStatusBarOrientationNotification + object:nil]; +#pragma clang diagnostic pop + +#elif CLS_TARGET_OS_OSX + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(willBecomeActive:) + name:@"NSApplicationWillBecomeActiveNotification" + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didBecomeInactive:) + name:@"NSApplicationDidResignActiveNotification" + object:nil]; +#endif +} + +- (void)captureInitialNotificationStates { +#if TARGET_OS_IOS + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + UIInterfaceOrientation statusBarOrientation = + [FIRCLSApplicationSharedInstance() statusBarOrientation]; +#endif + + // It's nice to do this async, so we don't hold up the main thread while doing three + // consecutive IOs here. + dispatch_async(FIRCLSGetLoggingQueue(), ^{ + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSInBackgroundKey, @"0"); +#if TARGET_OS_IOS + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSDeviceOrientationKey, + [@(orientation) description]); + FIRCLSUserLoggingWriteInternalKeyValue(FIRCLSUIOrientationKey, + [@(statusBarOrientation) description]); +#endif + }); +} + +- (void)willBecomeActive:(NSNotification *)notification { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSInBackgroundKey, @NO); +} + +- (void)didBecomeInactive:(NSNotification *)notification { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSInBackgroundKey, @YES); +} + +#if TARGET_OS_IOS +- (void)didChangeOrientation:(NSNotification *)notification { + UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; + + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDeviceOrientationKey, @(orientation)); +} + +- (void)didChangeUIOrientation:(NSNotification *)notification { + UIInterfaceOrientation statusBarOrientation = + [FIRCLSApplicationSharedInstance() statusBarOrientation]; + + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSUIOrientationKey, @(statusBarOrientation)); +} +#endif + +#pragma mark - FIRCLSNetworkClientDelegate +- (BOOL)networkClientCanUseBackgroundSessions:(FIRCLSNetworkClient *)client { + return !FIRCLSApplicationIsExtension(); +} + +- (void)networkClient:(FIRCLSNetworkClient *)client + didFinishUploadWithPath:(NSString *)path + error:(NSError *)error { + // Route this through to the reports uploader. + // Since this callback happens after an upload finished, then we can assume that the original data + // collection was authorized. This isn't ideal, but it's better than trying to plumb the data + // collection token through all the system networking callbacks. + FIRCLSDataCollectionToken *token = [FIRCLSDataCollectionToken validToken]; + [[self uploader] reportUploadAtPath:path dataCollectionToken:token completedWithError:error]; +} + +#pragma mark - FIRCLSReportUploaderDelegate + +- (void)didCompletePackageSubmission:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)token + error:(NSError *)error { + if (!error) { + FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission successful"); + return; + } + + FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission failed with error %@", error); + FIRCLSSDKLog("Error: failed to submit report '%s'\n", error.description.UTF8String); + + [self retryUploadForReportAtPath:path dataCollectionToken:token]; +} + +- (void)didCompleteAllSubmissions { + [self.operationQueue addOperationWithBlock:^{ + // Dealloc the reports uploader. If we need it again (if we re-enqueued submissions from + // didCompletePackageSubmission:, we can just create it again + self->_uploader = nil; + + FIRCLSDeveloperLog("Crashlytics:Crash", @"report submission complete"); + }]; +} + +#pragma mark - UITest Helpers + +// Used only for internal data collection E2E testing +- (void)didSubmitReport { + if (reportSentCallback) { + dispatch_async(dispatch_get_main_queue(), ^{ + reportSentCallback(); + }); + } +} + ++ (void)setReportSentCallback:(void (^)(void))callback { + reportSentCallback = callback; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h new file mode 100644 index 00000000..9122370f --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h @@ -0,0 +1,36 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h" + +@class FIRCLSInstallIdentifierModel; + +@interface FIRCLSReportManager () <FIRCLSReportUploaderDelegate, FIRCLSReportUploaderDataSource> + +@property(nonatomic, strong) NSOperationQueue *operationQueue; +@property(nonatomic, strong) FIRCLSNetworkClient *networkClient; +@property(nonatomic, readonly) FIRCLSReportUploader *uploader; +@property(nonatomic, strong) FIRCLSFileManager *fileManager; + +@end + +@interface FIRCLSReportManager (PrivateMethods) + +- (BOOL)createLaunchFailureMarker; +- (BOOL)launchFailureMarkerPresent; + +- (BOOL)potentiallySubmittableCrashOccurred; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h new file mode 100644 index 00000000..8cc124a5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h @@ -0,0 +1,79 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRCLSDataCollectionToken; +@class FIRCLSInternalReport; +@class FIRCLSSettings; +@class FIRCLSFileManager; +@class FIRCLSNetworkClient; +@class FIRCLSReportUploader; +@class GDTCORTransport; + +@protocol FIRCLSReportUploaderDelegate; +@protocol FIRCLSReportUploaderDataSource; +@protocol FIRAnalyticsInterop; + +@interface FIRCLSReportUploader : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithQueue:(NSOperationQueue *)queue + delegate:(id<FIRCLSReportUploaderDelegate>)delegate + dataSource:(id<FIRCLSReportUploaderDataSource>)dataSource + client:(FIRCLSNetworkClient *)client + fileManager:(FIRCLSFileManager *)fileManager + analytics:(id<FIRAnalyticsInterop>)analytics NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, weak) id<FIRCLSReportUploaderDelegate> delegate; +@property(nonatomic, weak) id<FIRCLSReportUploaderDataSource> dataSource; + +@property(nonatomic, readonly) NSOperationQueue *operationQueue; +@property(nonatomic, readonly) FIRCLSNetworkClient *networkClient; +@property(nonatomic, readonly) FIRCLSFileManager *fileManager; + +- (BOOL)prepareAndSubmitReport:(FIRCLSInternalReport *)report + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent + withProcessing:(BOOL)shouldProcess; + +- (BOOL)uploadPackagedReportAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent; + +- (void)reportUploadAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + completedWithError:(NSError *)error; + +@end + +@protocol FIRCLSReportUploaderDelegate <NSObject> +@required + +- (void)didCompletePackageSubmission:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)token + error:(NSError *)error; +- (void)didCompleteAllSubmissions; + +@end + +@protocol FIRCLSReportUploaderDataSource <NSObject> +@required + +- (NSString *)googleAppID; +- (FIRCLSSettings *)settings; +- (GDTCORTransport *)googleTransport; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m new file mode 100644 index 00000000..2a601008 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.m @@ -0,0 +1,355 @@ +// Copyright 2019 Google +// +// 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. + +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSNetworkClient.h" +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h" +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h" +#import "Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h" +#import "Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h" + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#import "Crashlytics/Shared/FIRCLSConstants.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h" + +#import "GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h" + +@interface FIRCLSReportUploader () { + id<FIRAnalyticsInterop> _analytics; +} +@end + +@implementation FIRCLSReportUploader + +- (instancetype)initWithQueue:(NSOperationQueue *)queue + delegate:(id<FIRCLSReportUploaderDelegate>)delegate + dataSource:(id<FIRCLSReportUploaderDataSource>)dataSource + client:(FIRCLSNetworkClient *)client + fileManager:(FIRCLSFileManager *)fileManager + analytics:(id<FIRAnalyticsInterop>)analytics { + self = [super init]; + if (!self) { + return nil; + } + + _operationQueue = queue; + _delegate = delegate; + _dataSource = dataSource; + _networkClient = client; + _fileManager = fileManager; + _analytics = analytics; + + return self; +} + +#pragma mark - Packaging and Submission +- (BOOL)prepareAndSubmitReport:(FIRCLSInternalReport *)report + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent + withProcessing:(BOOL)shouldProcess { + __block BOOL success = NO; + + if (![dataCollectionToken isValid]) { + FIRCLSErrorLog(@"Data collection disabled and report will not be submitted"); + return NO; + } + + if (!self.dataSource.settings.orgID && !self.dataSource.settings.shouldUseNewReportEndpoint) { + FIRCLSDebugLog( + @"Skipping report with id '%@' this run of the app because Organization ID was " + @"nil. Report via the legacy endpoint will upload once settings are download successfully", + report.identifier); + return YES; + } + + FIRCLSApplicationActivity( + FIRCLSApplicationActivityDefault, @"Crashlytics Crash Report Processing", ^{ + if (shouldProcess) { + if (![self.fileManager moveItemAtPath:report.path + toDirectory:self.fileManager.processingPath]) { + FIRCLSErrorLog(@"Unable to move report for processing"); + return; + } + + // adjust the report's path, and process it + [report setPath:[self.fileManager.processingPath + stringByAppendingPathComponent:report.directoryName]]; + + FIRCLSSymbolResolver *resolver = [[FIRCLSSymbolResolver alloc] init]; + + FIRCLSProcessReportOperation *processOperation = + [[FIRCLSProcessReportOperation alloc] initWithReport:report resolver:resolver]; + + [processOperation start]; + } + + NSString *packagedPath; + + FIRCLSDebugLog(@"Preparing the report for the new endpoint: %d", + self.dataSource.settings.shouldUseNewReportEndpoint); + + // With the new report endpoint, the report is deleted once it is written to GDT + // Check if the report has a crash file before the report is moved or deleted + BOOL isCrash = report.isCrash; + + if (self.dataSource.settings.shouldUseNewReportEndpoint) { + // For the new endpoint, just move the .clsrecords from "processing" -> "prepared" + if (![self.fileManager moveItemAtPath:report.path + toDirectory:self.fileManager.preparedPath]) { + FIRCLSErrorLog(@"Unable to move report to prepared"); + return; + } + + packagedPath = [self.fileManager.preparedPath + stringByAppendingPathComponent:report.path.lastPathComponent]; + } else { + // For the legacy endpoint, continue generate the multipartmime file in "prepared-legacy" + FIRCLSPackageReportOperation *packageOperation = + [[FIRCLSPackageReportOperation alloc] initWithReport:report + fileManager:self.fileManager + settings:self.dataSource.settings]; + + [packageOperation start]; + packagedPath = packageOperation.finalPath; + if (!packagedPath) { + FIRCLSErrorLog(@"Unable to package report"); + return; + } + + if (![self.fileManager removeItemAtPath:report.path]) { + FIRCLSErrorLog(@"Unable to remove a processing item"); + } + } + + NSLog(@"[Firebase/Crashlytics] Packaged report with id '%@' for submission", + report.identifier); + + success = [self uploadPackagedReportAtPath:packagedPath + dataCollectionToken:dataCollectionToken + asUrgent:urgent]; + + // If the upload was successful and the report contained a crash forward it to Google + // Analytics. + if (success && isCrash) { + [FIRCLSFCRAnalytics logCrashWithTimeStamp:report.crashedOnDate.timeIntervalSince1970 + toAnalytics:self->_analytics]; + } + }); + + return success; +} + +- (BOOL)submitPackageMultipartMimeAtPath:(NSString *)multipartmimePath + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + synchronously:(BOOL)synchronous { + FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports", "Submitting %@ %@", + synchronous ? @"sync" : @"async", multipartmimePath); + + if ([[[self fileManager] fileSizeAtPath:multipartmimePath] unsignedIntegerValue] == 0) { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"Already-submitted report being ignored"); + return NO; + } + + NSTimeInterval timeout = 10.0; + + // If we are submitting synchronously, be more aggressive with the timeout. However, + // we only need this if the client does not support background requests. + if (synchronous && ![[self networkClient] supportsBackgroundRequests]) { + timeout = 2.0; + } + + NSMutableURLRequest *request = [self mutableRequestWithURL:[self reportURL] timeout:timeout]; + + [request setHTTPMethod:@"POST"]; + + if (![self fillInRequest:request forMultipartMimeDataAtPath:multipartmimePath]) { + return NO; + } + + [[self networkClient] startUploadRequest:request + filePath:multipartmimePath + dataCollectionToken:dataCollectionToken + immediately:synchronous]; + + return YES; +} + +- (BOOL)uploadPackagedReportAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + asUrgent:(BOOL)urgent { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"Submitting report%@", + urgent ? @" as urgent" : @""); + + // Check with the legacy path as the new path will always be contained in the legacy path + BOOL isNewPreparedPath = ![path containsString:self.fileManager.legacyPreparedPath]; + + if (isNewPreparedPath && self.dataSource.settings.shouldUseNewReportEndpoint) { + if (![dataCollectionToken isValid]) { + FIRCLSErrorLog(@"A report upload was requested with an invalid data collection token."); + return NO; + } + + FIRCLSReportAdapter *adapter = + [[FIRCLSReportAdapter alloc] initWithPath:path googleAppId:self.dataSource.googleAppID]; + + GDTCOREvent *event = [self.dataSource.googleTransport eventForTransport]; + event.dataObject = adapter; + event.qosTier = GDTCOREventQoSFast; // Bypass batching, send immediately + + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + __block BOOL success = YES; + + [self.dataSource.googleTransport + sendDataEvent:event + onComplete:^(BOOL wasWritten, NSError *error) { + if (!wasWritten) { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", + @"Failed to send crash report due to gdt write failure."); + success = NO; + return; + } + + if (error) { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", + @"Failed to send crash report due to gdt error: %@", + error.localizedDescription); + success = NO; + return; + } + + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", + @"Completed report submission with id: %@", path.lastPathComponent); + + if (urgent) { + dispatch_semaphore_signal(semaphore); + } + + [self cleanUpSubmittedReportAtPath:path]; + }]; + + if (urgent) { + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } + + return success; + + } else if (!isNewPreparedPath && !self.dataSource.settings.shouldUseNewReportEndpoint) { + return [self submitPackageMultipartMimeAtPath:path + dataCollectionToken:dataCollectionToken + synchronously:urgent]; + } + + // Unsupported state + return NO; +} + +- (BOOL)cleanUpSubmittedReportAtPath:(NSString *)path { + if (![[self fileManager] removeItemAtPath:path]) { + FIRCLSErrorLog(@"Unable to remove packaged submission"); + return NO; + } + + return YES; +} + +- (void)reportUploadAtPath:(NSString *)path + dataCollectionToken:(FIRCLSDataCollectionToken *)dataCollectionToken + completedWithError:(NSError *)error { + FIRCLSDeveloperLog("Crashlytics:Crash:Reports", @"completed submission of %@", path); + + if (!error) { + [self cleanUpSubmittedReportAtPath:path]; + } + + [[self delegate] didCompletePackageSubmission:path + dataCollectionToken:dataCollectionToken + error:error]; +} + +#pragma mark - Properties (TODO: Can delete once the experiment is over) + +- (NSURL *)reportURL { + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:FIRCLSReportsEndpoint]; + + [url appendComponent:@"/sdk-api/v1/platforms/"]; + [url appendComponent:FIRCLSApplicationGetPlatform()]; + [url appendComponent:@"/apps/"]; + [url appendComponent:self.dataSource.settings.fetchedBundleID]; + [url appendComponent:@"/reports"]; + + return [url URL]; +} + +- (NSString *)localeIdentifier { + return [[NSLocale currentLocale] localeIdentifier]; +} + +#pragma mark - URL Requests +- (NSMutableURLRequest *)mutableRequestWithURL:(NSURL *)url timeout:(NSTimeInterval)timeout { + NSMutableURLRequest *request = + [NSMutableURLRequest requestWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeout]; + + NSString *localeId = [self localeIdentifier]; + + [request setValue:@CLS_SDK_GENERATOR_NAME forHTTPHeaderField:FIRCLSNetworkUserAgent]; + [request setValue:FIRCLSNetworkApplicationJson forHTTPHeaderField:FIRCLSNetworkAccept]; + [request setValue:FIRCLSNetworkUTF8 forHTTPHeaderField:FIRCLSNetworkAcceptCharset]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkAcceptLanguage]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkContentLanguage]; + [request setValue:FIRCLSDeveloperToken forHTTPHeaderField:FIRCLSNetworkCrashlyticsDeveloperToken]; + [request setValue:FIRCLSApplicationGetSDKBundleID() + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientId]; + [request setValue:@CLS_SDK_DISPLAY_VERSION + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientDisplayVersion]; + [request setValue:[[self dataSource] googleAppID] + forHTTPHeaderField:FIRCLSNetworkCrashlyticsGoogleAppId]; + + return request; +} + +- (BOOL)fillInRequest:(NSMutableURLRequest *)request forMultipartMimeDataAtPath:(NSString *)path { + NSString *boundary = [[path lastPathComponent] stringByDeletingPathExtension]; + + [request setValue:[FIRCLSMultipartMimeStreamEncoder + contentTypeHTTPHeaderValueWithBoundary:boundary] + forHTTPHeaderField:@"Content-Type"]; + + NSNumber *fileSize = [[self fileManager] fileSizeAtPath:path]; + if (fileSize == nil) { + FIRCLSErrorLog(@"Could not determine size of multipart mime file"); + return NO; + } + + [request setValue:[fileSize stringValue] forHTTPHeaderField:@"Content-Length"]; + + return YES; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h new file mode 100644 index 00000000..020890d9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader_Private.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportUploader.h" + +@interface FIRCLSReportUploader (PrivateMethods) + +@property(nonatomic, readonly) NSURL *reportURL; + +- (NSMutableURLRequest *)mutableRequestWithURL:(NSURL *)url timeout:(NSTimeInterval)timeout; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h new file mode 100644 index 00000000..147bc7bb --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRApp; +@class FBLPromise<T>; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCLSDataCollectionArbiter : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict; + +- (BOOL)isLegacyDataCollectionKeyInPlist; + +- (BOOL)isCrashlyticsCollectionEnabled; + +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled; + +// Returns a promise that is fulfilled once data collection is enabled. +- (FBLPromise<NSNumber *> *)waitForCrashlyticsCollectionEnabled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m new file mode 100644 index 00000000..f47d8dc5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.m @@ -0,0 +1,148 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h" + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +#import "Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h" + +// The legacy data collection setting allows Fabric customers to turn off auto- +// initialization, but can be overridden by calling [Fabric with:]. +// +// While we support Fabric, we must have two different versions, because +// they require these slightly different semantics. +NSString *const FIRCLSLegacyCrashlyticsCollectionKey = @"firebase_crashlytics_collection_enabled"; + +// The new data collection setting can be set by an API that is stored in FIRCLSUserDefaults +NSString *const FIRCLSDataCollectionEnabledKey = @"com.crashlytics.data_collection"; + +// The new data collection setting also allows Firebase customers to turn off data +// collection in their Info.plist, and can be overridden by setting it to true using +// the setCrashlyticsCollectionEnabled API. +NSString *const FIRCLSCrashlyticsCollectionKey = @"FirebaseCrashlyticsCollectionEnabled"; + +typedef NS_ENUM(NSInteger, FIRCLSDataCollectionSetting) { + FIRCLSDataCollectionSettingNotSet = 0, + FIRCLSDataCollectionSettingEnabled = 1, + FIRCLSDataCollectionSettingDisabled = 2, +}; + +@interface FIRCLSDataCollectionArbiter () { + NSLock *_mutex; + FBLPromise *_dataCollectionEnabled; + BOOL _promiseResolved; + FIRApp *_app; + NSDictionary *_appInfo; +} +@end + +@implementation FIRCLSDataCollectionArbiter + +- (instancetype)initWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict { + self = [super init]; + if (self) { + _mutex = [[NSLock alloc] init]; + _appInfo = dict; + _app = app; + if ([FIRCLSDataCollectionArbiter isCrashlyticsCollectionEnabledWithApp:app withAppInfo:dict]) { + _dataCollectionEnabled = [FBLPromise resolvedWith:nil]; + _promiseResolved = YES; + } else { + _dataCollectionEnabled = [FBLPromise pendingPromise]; + _promiseResolved = NO; + } + } + + return self; +} + +/* + * Legacy collection key that we provide for customers to disable Crash reporting. + * Customers can later turn on Crashlytics using Fabric.with if they choose to do so. + * + * This flag is unsupported for the "New SDK" + */ +- (BOOL)isLegacyDataCollectionKeyInPlist { + if ([_appInfo objectForKey:FIRCLSLegacyCrashlyticsCollectionKey]) { + return true; + } + + return false; +} + +// This functionality is called in the initializer before self is fully initialized, +// so a class method is used. The instance method below allows for a consistent clean API. ++ (BOOL)isCrashlyticsCollectionEnabledWithApp:(FIRApp *)app withAppInfo:(NSDictionary *)dict { + FIRCLSDataCollectionSetting stickySetting = [FIRCLSDataCollectionArbiter stickySetting]; + if (stickySetting != FIRCLSDataCollectionSettingNotSet) { + return stickySetting == FIRCLSDataCollectionSettingEnabled; + } + + id firebaseCrashlyticsCollectionEnabled = [dict objectForKey:FIRCLSCrashlyticsCollectionKey]; + if ([firebaseCrashlyticsCollectionEnabled isKindOfClass:[NSString class]] || + [firebaseCrashlyticsCollectionEnabled isKindOfClass:[NSNumber class]]) { + return [firebaseCrashlyticsCollectionEnabled boolValue]; + } + + return [app isDataCollectionDefaultEnabled]; +} + +- (BOOL)isCrashlyticsCollectionEnabled { + return [FIRCLSDataCollectionArbiter isCrashlyticsCollectionEnabledWithApp:_app + withAppInfo:_appInfo]; +} + +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled { + FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults]; + FIRCLSDataCollectionSetting setting = + enabled ? FIRCLSDataCollectionSettingEnabled : FIRCLSDataCollectionSettingDisabled; + [userDefaults setInteger:setting forKey:FIRCLSDataCollectionEnabledKey]; + [userDefaults synchronize]; + + [_mutex lock]; + if (enabled) { + if (!_promiseResolved) { + [_dataCollectionEnabled fulfill:nil]; + _promiseResolved = YES; + } + } else { + if (_promiseResolved) { + _dataCollectionEnabled = [FBLPromise pendingPromise]; + _promiseResolved = NO; + } + } + [_mutex unlock]; +} + ++ (FIRCLSDataCollectionSetting)stickySetting { + FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults]; + return [userDefaults integerForKey:FIRCLSDataCollectionEnabledKey]; +} + +- (FBLPromise *)waitForCrashlyticsCollectionEnabled { + FBLPromise *result = nil; + [_mutex lock]; + result = _dataCollectionEnabled; + [_mutex unlock]; + return result; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h new file mode 100644 index 00000000..4ab2bb66 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h @@ -0,0 +1,45 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * A FIRCLSDataCollectionToken represents having permission to upload data. A data collection token + * is either valid or nil. Every function that directly initiates a network operation that will + * result in data collection must check to make sure it has been passed a valid token. Tokens should + * only be created when either (1) automatic data collection is enabled, or (2) the user has + * explicitly given permission to collect data for a particular purpose, using the API. For all the + * functions in between, the data collection token getting passed as an argument helps to document + * and enforce the flow of data collection permission through the SDK. + */ +@interface FIRCLSDataCollectionToken : NSObject + +/** + * Creates a valid token. Only call this method when either (1) automatic data collection is + * enabled, or (2) the user has explicitly given permission to collect data for a particular + * purpose, using the API. + */ ++ (instancetype)validToken; + +/** + * Use this to verify that a token is valid. If this is called on a nil instance, it will return NO. + * @return YES. + */ +- (BOOL)isValid; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m new file mode 100644 index 00000000..5dbde6ea --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.m @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" + +@implementation FIRCLSDataCollectionToken + ++ (instancetype)validToken { + return [[FIRCLSDataCollectionToken alloc] init]; +} + +- (BOOL)isValid { + return YES; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h new file mode 100644 index 00000000..f93a3b01 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h @@ -0,0 +1,84 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h" + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCLSURLSession : NSObject { + id<NSURLSessionDelegate> _delegate; + NSOperationQueue *_delegateQueue; + NSURLSessionConfiguration *_configuration; + NSMutableSet *_taskSet; + dispatch_queue_t _queue; + + NSString *_sessionDescription; +} + ++ (BOOL)NSURLSessionShouldBeUsed; + ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(nullable id<NSURLSessionDelegate>)delegate + delegateQueue:(nullable NSOperationQueue *)queue; + +@property(nonatomic, readonly, retain) NSOperationQueue *delegateQueue; +@property(nonatomic, readonly, retain) id<NSURLSessionDelegate> delegate; +@property(nonatomic, readonly, copy) NSURLSessionConfiguration *configuration; + +@property(nonatomic, copy) NSString *sessionDescription; + +- (void)getTasksWithCompletionHandler: + (void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler; + +// task creation - suitable for background operations +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request; +- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url; + +// convenience methods (that are not available for background sessions +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request + completionHandler:(nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler; +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request; + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (nullable void (^)(NSURL *targetPath, + NSURLResponse *response, + NSError *error))completionHandler; + +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request + fromFile:(NSURL *)fileURL + completionHandler: + (nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler; + +- (void)invalidateAndCancel; +- (void)finishTasksAndInvalidate; + +@end + +NS_ASSUME_NONNULL_END + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m new file mode 100644 index 00000000..67615a52 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.m @@ -0,0 +1,346 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h" + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h" + +#define DELEGATE ((id<NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>)self->_delegate) + +@interface FIRCLSURLSession () <FIRCLSURLSessionDownloadDelegate> + +@property(nonatomic, retain) NSOperationQueue *delegateQueue; +@property(nonatomic, retain) id<NSURLSessionDelegate> delegate; +@property(nonatomic, copy) NSURLSessionConfiguration *configuration; + +@end + +@implementation FIRCLSURLSession + +@synthesize delegate = _delegate; +@synthesize delegateQueue = _delegateQueue; +@synthesize configuration = _configuration; +@synthesize sessionDescription = _sessionDescription; + ++ (BOOL)NSURLSessionShouldBeUsed { + if (!NSClassFromString(@"NSURLSession")) { + return NO; + } + + // We use this as a proxy to verify that we are on at least iOS 8 or 10.10. The first OSes that + // has NSURLSession were fairly unstable. + return [[NSURLSessionConfiguration class] + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]; +} + ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration { + return [self sessionWithConfiguration:configuration delegate:nil delegateQueue:nil]; +} + ++ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(nullable id<NSURLSessionDelegate>)delegate + delegateQueue:(nullable NSOperationQueue *)queue { + if ([self NSURLSessionShouldBeUsed]) { + return [NSURLSession sessionWithConfiguration:configuration + delegate:delegate + delegateQueue:queue]; + } + + if (!configuration) { + return nil; + } + +#if __has_feature(objc_arc) + FIRCLSURLSession *session = [self new]; +#else + FIRCLSURLSession *session = [[self new] autorelease]; +#endif + [session setDelegate:delegate]; + // When delegate exists, but delegateQueue is nil, create a serial queue like NSURLSession + // documents. + if (delegate && !queue) { + queue = [self newDefaultDelegateQueue]; + } + session.delegateQueue = queue; + session.configuration = configuration; + return (NSURLSession *)session; +} + ++ (NSOperationQueue *)newDefaultDelegateQueue { + NSOperationQueue *delegateQueue = [[NSOperationQueue alloc] init]; + delegateQueue.name = [NSString stringWithFormat:@"%@ %p", NSStringFromClass(self), self]; + delegateQueue.maxConcurrentOperationCount = 1; + return delegateQueue; +} + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _queue = dispatch_queue_create("com.crashlytics.URLSession", 0); + + return self; +} + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_taskSet release]; + [_delegate release]; + [_delegateQueue release]; + [_configuration release]; + +#if !OS_OBJECT_USE_OBJC + dispatch_release(_queue); +#endif + + [super dealloc]; +} +#endif + +#pragma mark - Managing the Session + +- (void)invalidateAndCancel { + dispatch_sync(_queue, ^{ + for (FIRCLSURLSessionTask *task in self->_taskSet) { + [task cancel]; + } + }); + + self.delegate = nil; +} + +- (void)finishTasksAndInvalidate { + self.delegate = nil; +} + +#pragma mark - + +- (void)getTasksWithCompletionHandler: + (void (^)(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks))completionHandler { + [[self delegateQueue] addOperationWithBlock:^{ + // TODO - this is totally wrong, but better than not calling back at all + completionHandler(@[], @[], @[]); + }]; +} + +- (void)removeTaskFromSet:(FIRCLSURLSessionTask *)task { + dispatch_async(_queue, ^{ + [self->_taskSet removeObject:task]; + }); +} + +- (void)configureTask:(FIRCLSURLSessionTask *)task + withRequest:(NSURLRequest *)request + block:(void (^)(NSMutableURLRequest *mutableRequest))block { + NSMutableURLRequest *modifiedRequest = [request mutableCopy]; + + dispatch_sync(_queue, ^{ + [self->_taskSet addObject:task]; + + // TODO: this isn't allowed to overwrite existing headers + for (NSString *key in [self->_configuration HTTPAdditionalHeaders]) { + [modifiedRequest addValue:[[self->_configuration HTTPAdditionalHeaders] objectForKey:key] + forHTTPHeaderField:key]; + } + }); + + if (block) { + block(modifiedRequest); + } + + [task setOriginalRequest:modifiedRequest]; + [task setDelegate:self]; + +#if !__has_feature(objc_arc) + [modifiedRequest release]; +#endif +} + +- (BOOL)shouldInvokeDelegateSelector:(SEL)selector forTask:(FIRCLSURLSessionTask *)task { + return [task invokesDelegate] && [_delegate respondsToSelector:selector]; +} + +#pragma mark Task Creation +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request + fromFile:(NSURL *)fileURL { + return [self uploadTaskWithRequest:request fromFile:fileURL completionHandler:nil]; +} + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request { + return [self downloadTaskWithRequest:request completionHandler:nil]; +} + +- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url { + return [self downloadTaskWithRequest:[NSURLRequest requestWithURL:url]]; +} + +#pragma mark Async Convenience Methods +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request + completionHandler:(nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler { + FIRCLSURLSessionDataTask *task = [FIRCLSURLSessionDataTask task]; + + if (completionHandler) { + [task setCompletionHandler:completionHandler]; + [task setInvokesDelegate:NO]; + } + + [self configureTask:task withRequest:request block:nil]; + + return (NSURLSessionDataTask *)task; +} + +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request { + return [self dataTaskWithRequest:request completionHandler:nil]; +} + +- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request + fromFile:(NSURL *)fileURL + completionHandler: + (nullable void (^)(NSData *data, + NSURLResponse *response, + NSError *error))completionHandler { + FIRCLSURLSessionUploadTask *task = [FIRCLSURLSessionUploadTask task]; + + if (completionHandler) { + [task setCompletionHandler:completionHandler]; + [task setInvokesDelegate:NO]; + } + + [self configureTask:task + withRequest:request + block:^(NSMutableURLRequest *mutableRequest) { + // you cannot set up both of these, and we'll be using the stream here + [mutableRequest setHTTPBody:nil]; + [mutableRequest setHTTPBodyStream:[NSInputStream inputStreamWithURL:fileURL]]; + }]; + + return (NSURLSessionUploadTask *)task; +} + +- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (nullable void (^)(NSURL *targetPath, + NSURLResponse *response, + NSError *error))completionHandler { + FIRCLSURLSessionDownloadTask *task = [FIRCLSURLSessionDownloadTask task]; + + if (completionHandler) { + [task setDownloadCompletionHandler:completionHandler]; + [task setInvokesDelegate:NO]; + } + + [self configureTask:task withRequest:request block:nil]; + + return (NSURLSessionDownloadTask *)task; +} + +#pragma mark FIRCLSURLSessionTaskDelegate +- (NSURLRequest *)task:(FIRCLSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request { + // just accept the proposed redirection + return request; +} + +- (void)task:(FIRCLSURLSessionTask *)task didCompleteWithError:(NSError *)error { + if (![self shouldInvokeDelegateSelector:@selector(URLSession:task:didCompleteWithError:) + forTask:task]) { + [self removeTaskFromSet:task]; + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + task:(NSURLSessionTask *)task + didCompleteWithError:error]; + + // Note that you *cannot* clean up here, because this method could be run asynchronously with + // the delegate methods that care about the state of the task + [self removeTaskFromSet:task]; + }]; +} + +#pragma mark FIRCLSURLSessionDataTask +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response { + if (![self shouldInvokeDelegateSelector:@selector + (URLSession:dataTask:didReceiveResponse:completionHandler:) + forTask:task]) { + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + dataTask:(NSURLSessionDataTask *)task + didReceiveResponse:response + completionHandler:^(NSURLSessionResponseDisposition disposition){ + // nothing to do here + }]; + }]; +} + +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveData:(NSData *)data { + if (![self shouldInvokeDelegateSelector:@selector(URLSession:dataTask:didReceiveData:) + forTask:task]) { + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + dataTask:(NSURLSessionDataTask *)task + didReceiveData:data]; + }]; +} + +#pragma mark FIRCLSURLSessionDownloadDelegate +- (void)downloadTask:(FIRCLSURLSessionDownloadTask *)task didFinishDownloadingToURL:(NSURL *)url { + if (![self shouldInvokeDelegateSelector:@selector(URLSession: + downloadTask:didFinishDownloadingToURL:) + forTask:task]) { + // We have to be certain that we cleanup only once the delegate no longer cares about the state + // of the task being changed. In the case of download, this is either after the delegate method + // has been invoked, or here, if the delegate doesn't care. + [task cleanup]; + return; + } + + [_delegateQueue addOperationWithBlock:^{ + [DELEGATE URLSession:(NSURLSession *)self + downloadTask:(NSURLSessionDownloadTask *)task + didFinishDownloadingToURL:url]; + + // Cleanup for the download tasks is a little complex. As long as we do it only after + // the delegate has been informed of the completed download, we are ok. + [task cleanup]; + }]; +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsession) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h new file mode 100644 index 00000000..9f3ead01 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <Foundation/Foundation.h> + +#define FIRCLSURLSESSION_REQUIRED (!TARGET_OS_WATCH && !TARGET_OS_TV) + +// These macros generate a function to force a symbol for the containing .o, to work around an issue +// where strip will not strip debug information without a symbol to strip. +#define CONCAT_EXPANDED(a, b) a##b +#define CONCAT(a, b) CONCAT_EXPANDED(a, b) +#define DUMMY_FUNCTION_NAME(x) CONCAT(fircls_strip_this_, x) +#define INJECT_STRIP_SYMBOL(x) \ + void DUMMY_FUNCTION_NAME(x)(void) { \ + } diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h new file mode 100644 index 00000000..6efb0294 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h @@ -0,0 +1,42 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +@interface FIRCLSURLSessionConfiguration : NSObject <NSCopying> { + NSDictionary *_additionalHeaders; + NSURLCache *_URLCache; + NSHTTPCookieAcceptPolicy _cookiePolicy; +} + ++ (NSURLSessionConfiguration *)defaultSessionConfiguration; ++ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; ++ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier; ++ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier; + +@property(nonatomic, copy) NSDictionary *HTTPAdditionalHeaders; +@property(nonatomic, retain) NSURLCache *URLCache; +@property(nonatomic, assign) NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy; +@property(nonatomic, assign) BOOL sessionSendsLaunchEvents; +@property(nonatomic, assign) NSTimeInterval timeoutIntervalForRequest; +@property(nonatomic, assign) NSTimeInterval timeoutIntervalForResource; +@property(nonatomic, assign) BOOL allowsCellularAccess; + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m new file mode 100644 index 00000000..f27779b6 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.m @@ -0,0 +1,92 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionConfiguration.h" + +@implementation FIRCLSURLSessionConfiguration + +@synthesize URLCache = _URLCache; +@synthesize HTTPAdditionalHeaders = _additionalHeaders; +@synthesize HTTPCookieAcceptPolicy = _cookiePolicy; + ++ (NSURLSessionConfiguration *)defaultSessionConfiguration { + if ([FIRCLSURLSession NSURLSessionShouldBeUsed]) { + return [NSURLSessionConfiguration defaultSessionConfiguration]; + } + +#if __has_feature(objc_arc) + return [self new]; +#else + return [[self new] autorelease]; +#endif +} + ++ (NSURLSessionConfiguration *)ephemeralSessionConfiguration { + if ([FIRCLSURLSession NSURLSessionShouldBeUsed]) { + return [NSURLSessionConfiguration ephemeralSessionConfiguration]; + } + +#if __has_feature(objc_arc) + return [self new]; +#else + return [[self new] autorelease]; +#endif +} + ++ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier { + return [self backgroundSessionConfigurationWithIdentifier:identifier]; +} + ++ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier { + if (![FIRCLSURLSession NSURLSessionShouldBeUsed]) { + return nil; + } + + if ([[NSURLSessionConfiguration class] + respondsToSelector:@selector(backgroundSessionConfigurationWithIdentifier:)]) { + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; + } + + return [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:identifier]; +} + +- (id)copyWithZone:(NSZone *)zone { + FIRCLSURLSessionConfiguration *configuration; + + configuration = [FIRCLSURLSessionConfiguration new]; + [configuration setHTTPAdditionalHeaders:[self HTTPAdditionalHeaders]]; + + return configuration; +} + +// This functionality is not supported by the wrapper, so we just stub it out +- (BOOL)sessionSendsLaunchEvents { + return NO; +} + +- (void)setSessionSendsLaunchEvents:(BOOL)sessionSendsLaunchEvents { +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessionconfiguration) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h new file mode 100644 index 00000000..7171a6b1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +@interface FIRCLSURLSession (PrivateMethods) + +- (void)runOnDelegateQueue:(void (^)(void))block; + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h new file mode 100644 index 00000000..e64419ab --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h" + +@interface FIRCLSURLSessionDataTask : FIRCLSURLSessionTask { + void (^_completionHandler)(NSData *data, NSURLResponse *response, NSError *error); + NSURLConnection *_connection; + NSMutableData *_data; + NSString *_taskDescription; +} + +@property(nonatomic, copy) NSString *taskDescription; + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m new file mode 100644 index 00000000..3059e53e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.m @@ -0,0 +1,124 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h" + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h" + +#define DELEGATE ((id<FIRCLSURLSessionDataDelegate>)[self delegate]) + +@interface FIRCLSURLSessionDataTask () <NSURLConnectionDelegate> +@end + +@implementation FIRCLSURLSessionDataTask + +@synthesize connection = _connection; +@synthesize completionHandler = _completionHandler; +@synthesize taskDescription = _taskDescription; + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_connection release]; + [_completionHandler release]; + [_taskDescription release]; + [_data release]; + + [super dealloc]; +} +#endif + +- (void)resume { + dispatch_async([self queue], ^{ + NSURLConnection *connection; + + if ([self connection]) { + return; + } + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + connection = [[NSURLConnection alloc] initWithRequest:[self originalRequest] + delegate:self + startImmediately:NO]; +#pragma clang diagnostic pop + + [self setConnection:connection]; + + // bummer we have to do this on a runloop, but other mechanisms require iOS 5 or 10.7 + [connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; +#if !__has_feature(objc_arc) + [connection release]; +#endif + [connection start]; + }); +} + +- (void)complete { + // call completion handler first + if (_completionHandler) { + // this should go to another queue + _completionHandler(_data, [self response], [self error]); + } + + // and then finally, call the session delegate completion + [DELEGATE task:self didCompleteWithError:[self error]]; +} + +- (void)cancel { + [self.connection cancel]; +} + +#pragma mark NSURLConnectionDelegate +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { + dispatch_async([self queue], ^{ + [DELEGATE task:self didReceiveResponse:response]; + + [self setResponse:response]; + }); +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + dispatch_async([self queue], ^{ + if (!self->_data) { + self->_data = [NSMutableData new]; + } + + [self->_data appendData:data]; + [DELEGATE task:self didReceiveData:data]; + }); +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + dispatch_async([self queue], ^{ + [self setError:error]; + [self complete]; + }); +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + dispatch_async([self queue], ^{ + [self complete]; + }); +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessiondatatask) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h new file mode 100644 index 00000000..e9f4e1a3 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h @@ -0,0 +1,43 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h" + +@protocol FIRCLSURLSessionDataDelegate; + +@interface FIRCLSURLSessionDataTask () + +@property(nonatomic, retain) NSURLConnection *connection; +@property(nonatomic, copy) void (^completionHandler) + (NSData *data, NSURLResponse *response, NSError *error); + +- (void)complete; + +@end + +@protocol FIRCLSURLSessionDataDelegate <FIRCLSURLSessionTaskDelegate> +@required + +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveResponse:(NSURLResponse *)response; +- (void)task:(FIRCLSURLSessionDataTask *)task didReceiveData:(NSData *)data; + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h new file mode 100644 index 00000000..e254b6a5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h" + +@protocol FIRCLSURLSessionDownloadDelegate; + +@interface FIRCLSURLSessionDownloadTask : FIRCLSURLSessionDataTask { + void (^_downloadCompletionHandler)(NSURL *targetPath, NSURLResponse *response, NSError *error); + NSOutputStream *_outputStream; + NSURL *_targetURL; +} + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m new file mode 100644 index 00000000..121d9f93 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.m @@ -0,0 +1,157 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask.h" + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h" + +#define DELEGATE ((id<FIRCLSURLSessionDownloadDelegate>)[self delegate]) + +@interface FIRCLSURLSessionDownloadTask () <NSStreamDelegate> +@end + +@implementation FIRCLSURLSessionDownloadTask + +@synthesize downloadCompletionHandler = _downloadCompletionHandler; + +- (id)init { + self = [super init]; + if (!self) { + return nil; + } + +#if __has_feature(objc_arc) + _targetURL = [self temporaryFileURL]; + _outputStream = [NSOutputStream outputStreamWithURL:_targetURL append:NO]; +#else + _targetURL = [[self temporaryFileURL] retain]; + _outputStream = [[NSOutputStream outputStreamWithURL:_targetURL append:NO] retain]; +#endif + + [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + [_outputStream setDelegate:self]; + + return self; +} + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_downloadCompletionHandler release]; + [_targetURL release]; + [_outputStream release]; + + [super dealloc]; +} +#else +- (void)dealloc { + [_outputStream close]; + _outputStream.delegate = nil; +} +#endif + +- (NSURL *)temporaryFileURL { + NSString *tmpPath; + + tmpPath = [NSTemporaryDirectory() + stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]; + + // TODO: make this actually unique + return [NSURL fileURLWithPath:tmpPath isDirectory:NO]; +} + +- (void)cleanup { + // now, remove the temporary file + [[NSFileManager defaultManager] removeItemAtURL:_targetURL error:nil]; +} + +- (void)complete { + // This is an override of FIRCLSURLSessionDataTask's cleanup method + + // call completion handler first + if (_downloadCompletionHandler) { + _downloadCompletionHandler(_targetURL, [self response], [self error]); + } + + // followed by the session delegate, if there was no error + if (![self error]) { + [DELEGATE downloadTask:self didFinishDownloadingToURL:_targetURL]; + } + + // and then finally, call the session delegate completion + [DELEGATE task:self didCompleteWithError:[self error]]; +} + +- (void)writeDataToStream:(NSData *)data { + // open the stream first + if ([_outputStream streamStatus] == NSStreamStatusNotOpen) { + [_outputStream open]; + } + + if ([data respondsToSelector:@selector(enumerateByteRangesUsingBlock:)]) { + [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { + [self->_outputStream write:bytes maxLength:byteRange.length]; + }]; + + return; + } + + // fall back to the less-efficient mechanism for older OSes + [_outputStream write:[data bytes] maxLength:[data length]]; +} + +#pragma mark NSURLConnectionDelegate +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + dispatch_async([self queue], ^{ + [self writeDataToStream:data]; + }); +} + +- (void)completeForError { + dispatch_async([self queue], ^{ + [self->_outputStream close]; + [self->_connection cancel]; + if (![self error]) { + [self setError:[NSError errorWithDomain:@"FIRCLSURLSessionDownloadTaskError" + code:-1 + userInfo:nil]]; + } + [self complete]; + }); +} + +#pragma mark NSStreamDelegate +- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { + switch (eventCode) { + case NSStreamEventHasSpaceAvailable: + break; + case NSStreamEventErrorOccurred: + [self completeForError]; + break; + case NSStreamEventEndEncountered: + break; + default: + break; + } +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessiondownloadtask) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h new file mode 100644 index 00000000..51c449b8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDownloadTask_PrivateMethods.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask_PrivateMethods.h" + +@protocol FIRCLSURLSessionDownloadDelegate; + +@interface FIRCLSURLSessionDownloadTask () + +@property(nonatomic, copy) void (^downloadCompletionHandler) + (NSURL *targetPath, NSURLResponse *response, NSError *error); + +@end + +@protocol FIRCLSURLSessionDownloadDelegate <FIRCLSURLSessionDataDelegate> +@required + +- (void)downloadTask:(FIRCLSURLSessionDownloadTask *)task didFinishDownloadingToURL:(NSURL *)url; + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h new file mode 100644 index 00000000..92316464 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h @@ -0,0 +1,38 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@protocol FIRCLSURLSessionTaskDelegate; + +@interface FIRCLSURLSessionTask : NSObject { + __unsafe_unretained id<FIRCLSURLSessionTaskDelegate> _delegate; + + NSURLRequest* _originalRequest; + NSURLRequest* _currentRequest; + NSURLResponse* _response; + NSError* _error; + dispatch_queue_t _queue; + BOOL _invokesDelegate; +} + +@property(nonatomic, readonly, copy) NSURLRequest* originalRequest; +@property(nonatomic, readonly, copy) NSURLRequest* currentRequest; +@property(nonatomic, readonly, copy) NSURLResponse* response; + +@property(nonatomic, readonly, copy) NSError* error; + +- (void)resume; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m new file mode 100644 index 00000000..2672ebd9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.m @@ -0,0 +1,95 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h" + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask.h" + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession_PrivateMethods.h" +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h" + +@implementation FIRCLSURLSessionTask + ++ (instancetype)task { +#if __has_feature(objc_arc) + return [[self class] new]; + +#else + return [[[self class] new] autorelease]; +#endif +} + +@synthesize currentRequest = _currentRequest; +@synthesize originalRequest = _originalRequest; +@synthesize response = _response; +@synthesize error = _error; +@synthesize queue = _queue; +@synthesize invokesDelegate = _invokesDelegate; + +- (instancetype)init { + self = [super init]; + if (!self) { + return self; + } + + _queue = dispatch_queue_create("com.crashlytics.URLSessionTask", 0); + + _invokesDelegate = YES; + + return self; +} + +#if !__has_feature(objc_arc) +- (void)dealloc { + [_originalRequest release]; + [_currentRequest release]; + [_response release]; + [_error release]; + +#if !OS_OBJECT_USE_OBJC + dispatch_release(_queue); +#endif + + [super dealloc]; +} +#endif + +- (void)start { +#if DEBUG + assert(0 && "Must be implemented by FIRCLSURLSessionTask subclasses"); +#endif +} + +- (void)cancel { +#if DEBUG + assert(0 && "Must be implemented by FIRCLSURLSessionTask subclasses"); +#endif +} + +- (void)resume { +} + +- (void)cleanup { +} + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessiontask) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h new file mode 100644 index 00000000..42c6a3a8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionTask_PrivateMethods.h @@ -0,0 +1,55 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import <Foundation/Foundation.h> + +@protocol FIRCLSURLSessionTaskDelegate; + +@interface FIRCLSURLSessionTask () + ++ (instancetype)task; + +@property(nonatomic, assign) id<FIRCLSURLSessionTaskDelegate> delegate; + +@property(nonatomic, copy) NSURLRequest *originalRequest; +@property(nonatomic, copy) NSURLRequest *currentRequest; +@property(nonatomic, copy) NSURLResponse *response; + +@property(nonatomic, readonly) dispatch_queue_t queue; +@property(nonatomic, assign) BOOL invokesDelegate; + +- (void)cancel; + +@property(nonatomic, copy) NSError *error; + +- (void)cleanup; + +@end + +@protocol FIRCLSURLSessionTaskDelegate <NSObject> +@required + +- (NSURLRequest *)task:(FIRCLSURLSessionTask *)task + willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)request; + +- (void)task:(FIRCLSURLSessionTask *)task didCompleteWithError:(NSError *)error; + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h new file mode 100644 index 00000000..fdcbc0fa --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h @@ -0,0 +1,25 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionDataTask.h" + +@interface FIRCLSURLSessionUploadTask : FIRCLSURLSessionDataTask + +@end + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m new file mode 100644 index 00000000..8b211b77 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.m @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSessionAvailability.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/Tasks/FIRCLSURLSessionUploadTask.h" + +@implementation FIRCLSURLSessionUploadTask + +@end + +#else + +INJECT_STRIP_SYMBOL(clsurlsessionuploadtask) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h new file mode 100644 index 00000000..6df15326 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h @@ -0,0 +1,42 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +extern NSString *const FIRCLSUserDefaultsPathComponent; + +@interface FIRCLSUserDefaults : NSObject + ++ (instancetype)standardUserDefaults; + +- (id)objectForKey:(NSString *)key; +- (NSString *)stringForKey:(NSString *)key; +- (BOOL)boolForKey:(NSString *)key; +- (NSInteger)integerForKey:(NSString *)key; + +- (void)setObject:(id)object forKey:(NSString *)key; +- (void)setString:(NSString *)string forKey:(NSString *)key; +- (void)setBool:(BOOL)boolean forKey:(NSString *)key; +- (void)setInteger:(NSInteger)integer forKey:(NSString *)key; + +- (void)removeObjectForKey:(NSString *)key; +- (void)removeAllObjects; + +- (NSDictionary *)dictionaryRepresentation; + +- (void)migrateFromNSUserDefaults:(NSArray *)keysToMigrate; +- (id)objectForKeyByMigratingFromNSUserDefaults:(NSString *)keyToMigrateOrNil; +- (void)synchronize; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m new file mode 100644 index 00000000..40b1a169 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.m @@ -0,0 +1,372 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" + +#define CLS_USER_DEFAULTS_SERIAL_DISPATCH_QUEUE "com.crashlytics.CLSUserDefaults.access" +#define CLS_USER_DEFAULTS_SYNC_QUEUE "com.crashlytics.CLSUserDefaults.io" + +#define CLS_TARGET_CAN_WRITE_TO_DISK !TARGET_OS_TV + +// These values are required to stay the same between versions of the SDK so +// that when end users upgrade, their crashlytics data is still saved on disk. +#if !CLS_TARGET_CAN_WRITE_TO_DISK +static NSString *const FIRCLSNSUserDefaultsDataDictionaryKey = + @"com.crashlytics.CLSUserDefaults.user-default-key.data-dictionary"; +#endif + +NSString *const FIRCLSUserDefaultsPathComponent = @"CLSUserDefaults"; + +/** + * This class is an isolated re-implementation of NSUserDefaults which isolates our storage + * from that of our customers. This solves a number of issues we have seen in production, firstly + * that customers often delete or clear NSUserDefaults, unintentionally deleting our data. + * Further, we have seen thread safety issues in production with NSUserDefaults, as well as a number + * of bugs related to accessing NSUserDefaults before the device has been unlocked due to the + * NSFileProtection of NSUserDefaults. + */ +@interface FIRCLSUserDefaults () +@property(nonatomic, readwrite) BOOL synchronizeWroteToDisk; +#if CLS_TARGET_CAN_WRITE_TO_DISK +@property(nonatomic, copy, readonly) NSURL *directoryURL; +@property(nonatomic, copy, readonly) NSURL *fileURL; +#endif +@property(nonatomic, copy, readonly) + NSDictionary *persistedDataDictionary; // May only be safely accessed on the DictionaryQueue +@property(nonatomic, copy, readonly) + NSMutableDictionary *dataDictionary; // May only be safely accessed on the DictionaryQueue +@property(nonatomic, readonly) dispatch_queue_t + serialDictionaryQueue; // The queue on which all access to the dataDictionary occurs. +@property(nonatomic, readonly) + dispatch_queue_t synchronizationQueue; // The queue on which all disk access occurs. + +@end + +@implementation FIRCLSUserDefaults + +#pragma mark - singleton + ++ (instancetype)standardUserDefaults { + static FIRCLSUserDefaults *standardUserDefaults = nil; + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + standardUserDefaults = [[super allocWithZone:NULL] init]; + }); + + return standardUserDefaults; +} + +- (id)copyWithZone:(NSZone *)zone { + return self; +} + +- (id)init { + if (self = [super init]) { + _serialDictionaryQueue = + dispatch_queue_create(CLS_USER_DEFAULTS_SERIAL_DISPATCH_QUEUE, DISPATCH_QUEUE_SERIAL); + _synchronizationQueue = + dispatch_queue_create(CLS_USER_DEFAULTS_SYNC_QUEUE, DISPATCH_QUEUE_SERIAL); + + dispatch_sync(self.serialDictionaryQueue, ^{ +#if CLS_TARGET_CAN_WRITE_TO_DISK + self->_directoryURL = [self generateDirectoryURL]; + self->_fileURL = [[self->_directoryURL + URLByAppendingPathComponent:FIRCLSUserDefaultsPathComponent + isDirectory:NO] URLByAppendingPathExtension:@"plist"]; +#endif + self->_persistedDataDictionary = [self loadDefaults]; + if (!self->_persistedDataDictionary) { + self->_persistedDataDictionary = [NSDictionary dictionary]; + } + self->_dataDictionary = [self->_persistedDataDictionary mutableCopy]; + }); + } + return self; +} + +- (NSURL *)generateDirectoryURL { + NSURL *directoryBaseURL = + [[[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory + inDomains:NSUserDomainMask] lastObject]; + NSString *hostAppBundleIdentifier = [self getEscapedAppBundleIdentifier]; + return [self generateDirectoryURLForBaseURL:directoryBaseURL + hostAppBundleIdentifier:hostAppBundleIdentifier]; +} + +- (NSURL *)generateDirectoryURLForBaseURL:(NSURL *)directoryBaseURL + hostAppBundleIdentifier:(NSString *)hostAppBundleIdentifier { + NSURL *directoryURL = directoryBaseURL; + // On iOS NSApplicationSupportDirectory is contained in the app's bundle. On OSX, it is not (it is + // ~/Library/Application Support/). On OSX we create a directory + // ~/Library/Application Support/<app-identifier>/com.crashlytics/ for storing files. + // Mac App Store review process requires files to be written to + // ~/Library/Application Support/<app-identifier>/, + // so ~/Library/Application Support/com.crashlytics/<app-identifier>/ cannot be used. +#if !TARGET_OS_SIMULATOR && !TARGET_OS_EMBEDDED + if (hostAppBundleIdentifier) { + directoryURL = [directoryURL URLByAppendingPathComponent:hostAppBundleIdentifier]; + } +#endif + directoryURL = [directoryURL URLByAppendingPathComponent:@"com.crashlytics"]; + return directoryURL; +} + +- (NSString *)getEscapedAppBundleIdentifier { + return FIRCLSApplicationGetBundleIdentifier(); +} + +#pragma mark - fetch object + +- (id)objectForKey:(NSString *)key { + __block id result; + + dispatch_sync(self.serialDictionaryQueue, ^{ + result = [self->_dataDictionary objectForKey:key]; + }); + + return result; +} + +- (NSString *)stringForKey:(NSString *)key { + id result = [self objectForKey:key]; + + if (result != nil && [result isKindOfClass:[NSString class]]) { + return (NSString *)result; + } else { + return nil; + } +} + +- (BOOL)boolForKey:(NSString *)key { + id result = [self objectForKey:key]; + if (result != nil && [result isKindOfClass:[NSNumber class]]) { + return [(NSNumber *)result boolValue]; + } else { + return NO; + } +} + +// Defaults to 0 +- (NSInteger)integerForKey:(NSString *)key { + id result = [self objectForKey:key]; + if (result && [result isKindOfClass:[NSNumber class]]) { + return [(NSNumber *)result integerValue]; + } else { + return 0; + } +} + +#pragma mark - set object + +- (void)setObject:(id)object forKey:(NSString *)key { + dispatch_sync(self.serialDictionaryQueue, ^{ + [self->_dataDictionary setValue:object forKey:key]; + }); +} + +- (void)setString:(NSString *)string forKey:(NSString *)key { + [self setObject:string forKey:key]; +} + +- (void)setBool:(BOOL)boolean forKey:(NSString *)key { + [self setObject:[NSNumber numberWithBool:boolean] forKey:key]; +} + +- (void)setInteger:(NSInteger)integer forKey:(NSString *)key { + [self setObject:[NSNumber numberWithInteger:integer] forKey:key]; +} + +#pragma mark - removing objects + +- (void)removeObjectForKey:(NSString *)key { + dispatch_sync(self.serialDictionaryQueue, ^{ + [self->_dataDictionary removeObjectForKey:key]; + }); +} + +- (void)removeAllObjects { + dispatch_sync(self.serialDictionaryQueue, ^{ + [self->_dataDictionary removeAllObjects]; + }); +} + +#pragma mark - dictionary representation + +- (NSDictionary *)dictionaryRepresentation { + __block NSDictionary *result; + + dispatch_sync(self.serialDictionaryQueue, ^{ + result = [self->_dataDictionary copy]; + }); + + return result; +} + +#pragma mark - synchronization + +- (void)synchronize { + __block BOOL dirty = NO; + + // only write to the disk if the dictionaries have changed + dispatch_sync(self.serialDictionaryQueue, ^{ + dirty = ![self->_persistedDataDictionary isEqualToDictionary:self->_dataDictionary]; + }); + + _synchronizeWroteToDisk = dirty; + if (!dirty) { + return; + } + + NSDictionary *state = [self dictionaryRepresentation]; + dispatch_sync(self.synchronizationQueue, ^{ +#if CLS_TARGET_CAN_WRITE_TO_DISK + BOOL isDirectory = NO; + BOOL pathExists = [[NSFileManager defaultManager] fileExistsAtPath:[self->_directoryURL path] + isDirectory:&isDirectory]; + + if (!pathExists) { + NSError *error; + if (![[NSFileManager defaultManager] createDirectoryAtURL:self->_directoryURL + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + FIRCLSErrorLog(@"Failed to create directory with error: %@", error); + } + } + + if (![state writeToURL:self->_fileURL atomically:YES]) { + FIRCLSErrorLog(@"Unable to open file for writing at path %@", [self->_fileURL path]); + } else { +#if TARGET_OS_IOS + // We disable NSFileProtection on our file in order to allow us to access it even if the + // device is locked. + NSError *error; + if (![[NSFileManager defaultManager] + setAttributes:@{NSFileProtectionKey : NSFileProtectionNone} + ofItemAtPath:[self->_fileURL path] + error:&error]) { + FIRCLSErrorLog(@"Error setting NSFileProtection: %@", error); + } +#endif + } +#else + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + [defaults setObject:state forKey:FIRCLSNSUserDefaultsDataDictionaryKey]; + [defaults synchronize]; +#endif + }); + + dispatch_sync(self.serialDictionaryQueue, ^{ + self->_persistedDataDictionary = [self->_dataDictionary copy]; + }); +} + +- (NSDictionary *)loadDefaults { + __block NSDictionary *state = nil; + dispatch_sync(self.synchronizationQueue, ^{ +#if CLS_TARGET_CAN_WRITE_TO_DISK + BOOL isDirectory = NO; + BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:[self->_fileURL path] + isDirectory:&isDirectory]; + + if (fileExists && !isDirectory) { + state = [NSDictionary dictionaryWithContentsOfURL:self->_fileURL]; + if (nil == state) { + FIRCLSErrorLog(@"Failed to read existing UserDefaults file"); + } + } else if (!fileExists) { + // No file found. This is expected on first launch. + } else if (fileExists && isDirectory) { + FIRCLSErrorLog(@"Found directory where file expected. Removing conflicting directory"); + + NSError *error; + if (![[NSFileManager defaultManager] removeItemAtURL:self->_fileURL error:&error]) { + FIRCLSErrorLog(@"Error removing conflicting directory: %@", error); + } + } +#else + state = [[NSUserDefaults standardUserDefaults] dictionaryForKey:FIRCLSNSUserDefaultsDataDictionaryKey]; +#endif + }); + return state; +} + +#pragma mark - migration + +// This method migrates all keys specified from NSUserDefaults to FIRCLSUserDefaults +// To do so, we copy all known key-value pairs into FIRCLSUserDefaults, synchronize it, then +// remove the keys from NSUserDefaults and synchronize it. +- (void)migrateFromNSUserDefaults:(NSArray *)keysToMigrate { + BOOL didFindKeys = NO; + + // First, copy all of the keysToMigrate which are stored NSUserDefaults + for (NSString *key in keysToMigrate) { + id oldValue = [[NSUserDefaults standardUserDefaults] objectForKey:(NSString *)key]; + if (nil != oldValue) { + didFindKeys = YES; + [self setObject:oldValue forKey:key]; + } + } + + if (didFindKeys) { + // First synchronize FIRCLSUserDefaults such that all keysToMigrate in NSUserDefaults are stored + // in FIRCLSUserDefaults. At this point, data is duplicated. + [[FIRCLSUserDefaults standardUserDefaults] synchronize]; + + for (NSString *key in keysToMigrate) { + [[NSUserDefaults standardUserDefaults] removeObjectForKey:(NSString *)key]; + } + + // This should be our last interaction with NSUserDefaults. All data is migrated into + // FIRCLSUserDefaults + [[NSUserDefaults standardUserDefaults] synchronize]; + } +} + +// This method first queries FIRCLSUserDefaults to see if the key exist, and upon failure, +// searches for the key in NSUserDefaults, and migrates it if found. +- (id)objectForKeyByMigratingFromNSUserDefaults:(NSString *)keyToMigrateOrNil { + if (!keyToMigrateOrNil) { + return nil; + } + + id clsUserDefaultsValue = [self objectForKey:keyToMigrateOrNil]; + if (clsUserDefaultsValue != nil) { + return clsUserDefaultsValue; // if the value exists in FIRCLSUserDefaults, return it. + } + + id oldNSUserDefaultsValue = + [[NSUserDefaults standardUserDefaults] objectForKey:keyToMigrateOrNil]; + if (!oldNSUserDefaultsValue) { + return nil; // if the value also does not exist in NSUserDefaults, return nil. + } + + // Otherwise, the key exists in NSUserDefaults. Migrate it to FIRCLSUserDefaults + // and then return the associated value. + + // First store it in FIRCLSUserDefaults so in the event of a crash, data is not lost. + [self setObject:oldNSUserDefaultsValue forKey:keyToMigrateOrNil]; + [[FIRCLSUserDefaults standardUserDefaults] synchronize]; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:keyToMigrateOrNil]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + return oldNSUserDefaultsValue; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h new file mode 100644 index 00000000..783433c0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults_private.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h" + +@interface FIRCLSUserDefaults (Private) +- (BOOL)synchronizeWroteToDisk; +- (NSDictionary *)loadDefaults; +- (NSURL *)generateDirectoryURLForBaseURL:(NSURL *)directoryBaseURL + hostAppBundleIdentifier:(NSString *)hostAppBundleIdentifer; +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m new file mode 100644 index 00000000..8516216b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRCrashlytics.m @@ -0,0 +1,317 @@ +// Copyright 2019 Google +// +// 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. + +#include <stdatomic.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#include "Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#import "Crashlytics/Crashlytics/Components/FIRCLSHost.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionArbiter.h" +#import "Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSException.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" +#import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSFABHost.h" + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" +#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h" +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" + +#import "GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h" + +#if TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#endif + +FIRCLSContext _firclsContext; +dispatch_queue_t _firclsLoggingQueue; +dispatch_queue_t _firclsBinaryImageQueue; +dispatch_queue_t _firclsExceptionQueue; + +static atomic_bool _hasInitializedInstance; + +NSString *const FIRCLSGoogleTransportMappingID = @"1206"; + +/// Empty protocol to register with FirebaseCore's component system. +@protocol FIRCrashlyticsInstanceProvider <NSObject> +@end + +@interface FIRCrashlytics () <FIRLibrary, FIRCrashlyticsInstanceProvider> + +@property(nonatomic) BOOL didPreviouslyCrash; +@property(nonatomic, copy) NSString *googleAppID; +@property(nonatomic) FIRCLSDataCollectionArbiter *dataArbiter; +@property(nonatomic) FIRCLSFileManager *fileManager; +@property(nonatomic) FIRCLSReportManager *reportManager; +@property(nonatomic) GDTCORTransport *googleTransport; + +@end + +@implementation FIRCrashlytics + +#pragma mark - Singleton Support + +- (instancetype)initWithApp:(FIRApp *)app + appInfo:(NSDictionary *)appInfo + installations:(FIRInstallations *)installations + analytics:(id<FIRAnalyticsInterop>)analytics { + self = [super init]; + + if (self) { + bool expectedCalled = NO; + if (!atomic_compare_exchange_strong(&_hasInitializedInstance, &expectedCalled, YES)) { + FIRCLSErrorLog(@"Cannot instantiate more than one instance of Crashlytics."); + return nil; + } + + FIRCLSProfileMark mark = FIRCLSProfilingStart(); + + NSLog(@"[Firebase/Crashlytics] Version %@", @CLS_SDK_DISPLAY_VERSION); + + FIRCLSDeveloperLog("Crashlytics", @"Running on %@, %@ (%@)", FIRCLSHostModelInfo(), + FIRCLSHostOSDisplayVersion(), FIRCLSHostOSBuildVersion()); + + _googleTransport = [[GDTCORTransport alloc] initWithMappingID:FIRCLSGoogleTransportMappingID + transformers:nil + target:kGDTCORTargetCSH]; + + _fileManager = [[FIRCLSFileManager alloc] init]; + _googleAppID = app.options.googleAppID; + _dataArbiter = [[FIRCLSDataCollectionArbiter alloc] initWithApp:app withAppInfo:appInfo]; + + FIRCLSApplicationIdentifierModel *appModel = [[FIRCLSApplicationIdentifierModel alloc] init]; + FIRCLSSettings *settings = [[FIRCLSSettings alloc] initWithFileManager:_fileManager + appIDModel:appModel]; + + _reportManager = [[FIRCLSReportManager alloc] initWithFileManager:_fileManager + installations:installations + analytics:analytics + googleAppID:_googleAppID + dataArbiter:_dataArbiter + googleTransport:_googleTransport + appIDModel:appModel + settings:settings]; + + // Process did crash during previous execution + NSString *crashedMarkerFileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName]; + NSString *crashedMarkerFileFullPath = + [[_fileManager rootPath] stringByAppendingPathComponent:crashedMarkerFileName]; + _didPreviouslyCrash = [_fileManager fileExistsAtPath:crashedMarkerFileFullPath]; + + if (_didPreviouslyCrash) { + // Delete the crash file marker in the background ensure start up is as fast as possible + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + [self.fileManager removeItemAtPath:crashedMarkerFileFullPath]; + }); + } + + [[[_reportManager startWithProfilingMark:mark] then:^id _Nullable(NSNumber *_Nullable value) { + if (![value boolValue]) { + FIRCLSErrorLog(@"Crash reporting could not be initialized"); + } + return value; + }] catch:^void(NSError *error) { + FIRCLSErrorLog(@"Crash reporting failed to initialize with error: %@", error); + }]; + } + + return self; +} + ++ (void)load { + [FIRApp registerInternalLibrary:(Class<FIRLibrary>)self + withName:@"firebase-crashlytics" + withVersion:@CLS_SDK_DISPLAY_VERSION]; +} + ++ (NSArray<FIRComponent *> *)componentsToRegister { + FIRDependency *analyticsDep = + [FIRDependency dependencyWithProtocol:@protocol(FIRAnalyticsInterop)]; + + FIRComponentCreationBlock creationBlock = + ^id _Nullable(FIRComponentContainer *container, BOOL *isCacheable) { + if (!container.app.isDefaultApp) { + FIRCLSErrorLog(@"Crashlytics must be used with the default Firebase app."); + return nil; + } + + id<FIRAnalyticsInterop> analytics = FIR_COMPONENT(FIRAnalyticsInterop, container); + + FIRInstallations *installations = [FIRInstallations installationsWithApp:container.app]; + + *isCacheable = YES; + + return [[FIRCrashlytics alloc] initWithApp:container.app + appInfo:NSBundle.mainBundle.infoDictionary + installations:installations + analytics:analytics]; + }; + + FIRComponent *component = + [FIRComponent componentWithProtocol:@protocol(FIRCrashlyticsInstanceProvider) + instantiationTiming:FIRInstantiationTimingEagerInDefaultApp + dependencies:@[ analyticsDep ] + creationBlock:creationBlock]; + return @[ component ]; +} + ++ (instancetype)crashlytics { + // The container will return the same instance since isCacheable is set + + FIRApp *defaultApp = [FIRApp defaultApp]; // Missing configure will be logged here. + + // Get the instance from the `FIRApp`'s container. This will create a new instance the + // first time it is called, and since `isCacheable` is set in the component creation + // block, it will return the existing instance on subsequent calls. + id<FIRCrashlyticsInstanceProvider> instance = + FIR_COMPONENT(FIRCrashlyticsInstanceProvider, defaultApp.container); + + // In the component creation block, we return an instance of `FIRCrashlytics`. Cast it and + // return it. + return (FIRCrashlytics *)instance; +} + +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled { + [self.dataArbiter setCrashlyticsCollectionEnabled:enabled]; +} + +- (BOOL)isCrashlyticsCollectionEnabled { + return [self.dataArbiter isCrashlyticsCollectionEnabled]; +} + +#pragma mark - API: didCrashDuringPreviousExecution + +- (BOOL)didCrashDuringPreviousExecution { + return self.didPreviouslyCrash; +} + +- (void)processDidCrashDuringPreviousExecution { + NSString *crashedMarkerFileName = [NSString stringWithUTF8String:FIRCLSCrashedMarkerFileName]; + NSString *crashedMarkerFileFullPath = + [[self.fileManager rootPath] stringByAppendingPathComponent:crashedMarkerFileName]; + self.didPreviouslyCrash = [self.fileManager fileExistsAtPath:crashedMarkerFileFullPath]; + + if (self.didPreviouslyCrash) { + // Delete the crash file marker in the background ensure start up is as fast as possible + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + [self.fileManager removeItemAtPath:crashedMarkerFileFullPath]; + }); + } +} + +#pragma mark - API: Logging +- (void)log:(NSString *)msg { + FIRCLSLog(@"%@", msg); +} + +- (void)logWithFormat:(NSString *)format, ... { + va_list args; + va_start(args, format); + [self logWithFormat:format arguments:args]; + va_end(args); +} + +- (void)logWithFormat:(NSString *)format arguments:(va_list)args { + [self log:[[NSString alloc] initWithFormat:format arguments:args]]; +} + +#pragma mark - API: Accessors + +- (void)checkForUnsentReportsWithCompletion:(void (^)(BOOL))completion { + [[self.reportManager checkForUnsentReports] then:^id _Nullable(NSNumber *_Nullable value) { + completion([value boolValue]); + return nil; + }]; +} + +- (void)sendUnsentReports { + [self.reportManager sendUnsentReports]; +} + +- (void)deleteUnsentReports { + [self.reportManager deleteUnsentReports]; +} + +#pragma mark - API: setUserID +- (void)setUserID:(NSString *)userID { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSUserIdentifierKey, userID); +} + +#pragma mark - API: setCustomValue + +- (void)setCustomValue:(id)value forKey:(NSString *)key { + FIRCLSUserLoggingRecordUserKeyValue(key, value); +} + +#pragma mark - API: Development Platform +// These two methods are depercated by our own API, so +// its ok to implement them +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" ++ (void)setDevelopmentPlatformName:(NSString *)name { + [[self crashlytics] setDevelopmentPlatformName:name]; +} + ++ (void)setDevelopmentPlatformVersion:(NSString *)version { + [[self crashlytics] setDevelopmentPlatformVersion:version]; +} +#pragma clang diagnostic pop + +- (NSString *)developmentPlatformName { + FIRCLSErrorLog(@"developmentPlatformName is write-only"); + return nil; +} + +- (void)setDevelopmentPlatformName:(NSString *)developmentPlatformName { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDevelopmentPlatformNameKey, + developmentPlatformName); +} + +- (NSString *)developmentPlatformVersion { + FIRCLSErrorLog(@"developmentPlatformVersion is write-only"); + return nil; +} + +- (void)setDevelopmentPlatformVersion:(NSString *)developmentPlatformVersion { + FIRCLSUserLoggingRecordInternalKeyValue(FIRCLSDevelopmentPlatformVersionKey, + developmentPlatformVersion); +} + +#pragma mark - API: Errors and Exceptions +- (void)recordError:(NSError *)error { + FIRCLSUserLoggingRecordError(error, nil); +} + +- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel { + FIRCLSExceptionRecordModel(exceptionModel); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m new file mode 100644 index 00000000..e7ed9989 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRExceptionModel.m @@ -0,0 +1,42 @@ +// Copyright 2020 Google LLC +// +// 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. + +#import "Crashlytics/Crashlytics/Public/FIRExceptionModel.h" + +@interface FIRExceptionModel () + +@property(nonatomic, copy) NSString *name; +@property(nonatomic, copy) NSString *reason; + +@end + +@implementation FIRExceptionModel + +- (instancetype)initWithName:(NSString *)name reason:(NSString *)reason { + self = [super init]; + if (!self) { + return nil; + } + + _name = [name copy]; + _reason = [reason copy]; + + return self; +} + ++ (instancetype)exceptionModelWithName:(NSString *)name reason:(NSString *)reason { + return [[FIRExceptionModel alloc] initWithName:name reason:reason]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m new file mode 100644 index 00000000..4f9d60a4 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/FIRStackFrame.m @@ -0,0 +1,94 @@ +// Copyright 2020 Google LLC +// +// 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. + +#import "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h" + +@interface FIRStackFrame () + +@property(nonatomic, copy, nullable) NSString *symbol; +@property(nonatomic, copy, nullable) NSString *rawSymbol; +@property(nonatomic, copy, nullable) NSString *library; +@property(nonatomic, copy, nullable) NSString *fileName; +@property(nonatomic, assign) uint32_t lineNumber; +@property(nonatomic, assign) uint64_t offset; +@property(nonatomic, assign) uint64_t address; + +@property(nonatomic, assign) BOOL isSymbolicated; + +@end + +@implementation FIRStackFrame + +#pragma mark - Public Methods + +- (instancetype)initWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line { + self = [super init]; + if (!self) { + return nil; + } + + _symbol = [symbol copy]; + _fileName = [file copy]; + _lineNumber = (uint32_t)line; + + _isSymbolicated = true; + + return self; +} + ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line { + return [[FIRStackFrame alloc] initWithSymbol:symbol file:file line:line]; +} + +#pragma mark - Internal Methods + ++ (instancetype)stackFrame { + return [[self alloc] init]; +} + ++ (instancetype)stackFrameWithAddress:(NSUInteger)address { + FIRStackFrame *frame = [self stackFrame]; + + [frame setAddress:address]; + + return frame; +} + ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol { + FIRStackFrame *frame = [self stackFrame]; + + frame.symbol = symbol; + frame.rawSymbol = symbol; + + return frame; +} + +#pragma mark - Overrides + +- (NSString *)description { + if (self.isSymbolicated) { + return [NSString + stringWithFormat:@"{%@ - %@:%u}", [self fileName], [self symbol], [self lineNumber]]; + } + + if (self.fileName) { + return [NSString stringWithFormat:@"{[0x%llx] %@ - %@:%u}", [self address], [self fileName], + [self symbol], [self lineNumber]]; + } + + return [NSString + stringWithFormat:@"{[0x%llx + %u] %@}", [self address], [self lineNumber], [self symbol]]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h new file mode 100644 index 00000000..61dac77c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.h @@ -0,0 +1,73 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdint.h> +#include <sys/cdefs.h> + +#ifdef __OBJC__ +#import <Foundation/Foundation.h> +@class FIRStackFrame; +@class FIRExceptionModel; +#endif + +#define CLS_EXCEPTION_STRING_LENGTH_MAX (1024 * 16) + +typedef enum { + FIRCLSExceptionTypeUnknown = 0, + FIRCLSExceptionTypeObjectiveC = 1, + FIRCLSExceptionTypeCpp = 2, + // 3 was FIRCLSExceptionTypeJavascript + // Keeping these numbers the same just to be safe + FIRCLSExceptionTypeCustom = 4 +} FIRCLSExceptionType; + +typedef struct { + const char* path; + + void (*originalTerminateHandler)(void); + +#if !TARGET_OS_IPHONE + void* originalNSApplicationReportException; +#endif + + uint32_t maxCustomExceptions; +} FIRCLSExceptionReadOnlyContext; + +typedef struct { + uint32_t customExceptionCount; +} FIRCLSExceptionWritableContext; + +__BEGIN_DECLS + +void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext* roContext, + FIRCLSExceptionWritableContext* rwContext, + void* delegate); +void FIRCLSExceptionCheckHandlers(void* delegate); + +void FIRCLSExceptionRaiseTestObjCException(void) __attribute((noreturn)); +void FIRCLSExceptionRaiseTestCppException(void) __attribute((noreturn)); + +#ifdef __OBJC__ +void FIRCLSExceptionRecordModel(FIRExceptionModel* exceptionModel); +void FIRCLSExceptionRecordNSException(NSException* exception); +void FIRCLSExceptionRecord(FIRCLSExceptionType type, + const char* name, + const char* reason, + NSArray<FIRStackFrame*>* frames, + BOOL attemptDelivery); +#endif + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm new file mode 100644 index 00000000..29a4b826 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSException.mm @@ -0,0 +1,410 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#include "Crashlytics/Crashlytics/Handlers/FIRCLSException.h" + +#import "Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h" +#import "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h" + +#include "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSProcess.h" +#import "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h" +#include "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h" + +// C++/Objective-C exception handling +#include <cxxabi.h> +#include <exception> +#include <string> +#include <typeinfo> + +#if !TARGET_OS_IPHONE +#import <AppKit/NSApplication.h> +#import <objc/runtime.h> +#endif + +#pragma mark Prototypes +static void FIRCLSTerminateHandler(void); +#if !TARGET_OS_IPHONE +void FIRCLSNSApplicationReportException(id self, SEL cmd, NSException *exception); + +typedef void (*NSApplicationReportExceptionFunction)(id, SEL, NSException *); + +static BOOL FIRCLSIsNSApplicationCrashOnExceptionsEnabled(void); +static NSApplicationReportExceptionFunction FIRCLSOriginalNSExceptionReportExceptionFunction(void); +static Method FIRCLSGetNSApplicationReportExceptionMethod(void); + +#endif + +#pragma mark - API +void FIRCLSExceptionInitialize(FIRCLSExceptionReadOnlyContext *roContext, + FIRCLSExceptionWritableContext *rwContext, + void *delegate) { + if (!FIRCLSUnlinkIfExists(roContext->path)) { + FIRCLSSDKLog("Unable to reset the exception file %s\n", strerror(errno)); + } + + roContext->originalTerminateHandler = std::set_terminate(FIRCLSTerminateHandler); + +#if !TARGET_OS_IPHONE + // If FIRCLSApplicationSharedInstance is null, we don't need this + if (FIRCLSIsNSApplicationCrashOnExceptionsEnabled() && FIRCLSApplicationSharedInstance()) { + Method m = FIRCLSGetNSApplicationReportExceptionMethod(); + + roContext->originalNSApplicationReportException = + (void *)method_setImplementation(m, (IMP)FIRCLSNSApplicationReportException); + } +#endif + + rwContext->customExceptionCount = 0; +} + +void FIRCLSExceptionRecordModel(FIRExceptionModel *exceptionModel) { + const char *name = [[exceptionModel.name copy] UTF8String]; + const char *reason = [[exceptionModel.reason copy] UTF8String]; + + FIRCLSExceptionRecord(FIRCLSExceptionTypeCustom, name, reason, [exceptionModel.stackTrace copy], + NO); +} + +void FIRCLSExceptionRecordNSException(NSException *exception) { + FIRCLSSDKLog("Recording an NSException\n"); + + NSArray *returnAddresses = [exception callStackReturnAddresses]; + + NSString *name = [exception name]; + NSString *reason = [exception reason]; + + // It's tempting to try to make use of callStackSymbols here. But, the output + // of that function is not intended to be machine-readible. We could parse it, + // but that isn't really worthwhile, considering that address-based symbolication + // needs to work anyways. + + // package our frames up into the appropriate format + NSMutableArray *frames = [NSMutableArray new]; + + for (NSNumber *address in returnAddresses) { + [frames addObject:[FIRStackFrame stackFrameWithAddress:[address unsignedIntegerValue]]]; + } + + FIRCLSExceptionRecord(FIRCLSExceptionTypeObjectiveC, [name UTF8String], [reason UTF8String], + frames, YES); +} + +static void FIRCLSExceptionRecordFrame(FIRCLSFile *file, FIRStackFrame *frame) { + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryUint64(file, "pc", [frame address]); + + NSString *string = [frame symbol]; + if (string) { + FIRCLSFileWriteHashEntryHexEncodedString(file, "symbol", [string UTF8String]); + } + + FIRCLSFileWriteHashEntryUint64(file, "offset", [frame offset]); + + string = [frame library]; + if (string) { + FIRCLSFileWriteHashEntryHexEncodedString(file, "library", [string UTF8String]); + } + + string = [frame fileName]; + if (string) { + FIRCLSFileWriteHashEntryHexEncodedString(file, "file", [string UTF8String]); + } + + FIRCLSFileWriteHashEntryUint64(file, "line", [frame lineNumber]); + + FIRCLSFileWriteHashEnd(file); +} + +static bool FIRCLSExceptionIsNative(FIRCLSExceptionType type) { + return type == FIRCLSExceptionTypeObjectiveC || type == FIRCLSExceptionTypeCpp; +} + +static const char *FIRCLSExceptionNameForType(FIRCLSExceptionType type) { + switch (type) { + case FIRCLSExceptionTypeObjectiveC: + return "objective-c"; + case FIRCLSExceptionTypeCpp: + return "c++"; + case FIRCLSExceptionTypeCustom: + return "custom"; + default: + break; + } + + return "unknown"; +} + +void FIRCLSExceptionWrite(FIRCLSFile *file, + FIRCLSExceptionType type, + const char *name, + const char *reason, + NSArray<FIRStackFrame *> *frames) { + FIRCLSFileWriteSectionStart(file, "exception"); + + FIRCLSFileWriteHashStart(file); + + FIRCLSFileWriteHashEntryString(file, "type", FIRCLSExceptionNameForType(type)); + FIRCLSFileWriteHashEntryHexEncodedString(file, "name", name); + FIRCLSFileWriteHashEntryHexEncodedString(file, "reason", reason); + FIRCLSFileWriteHashEntryUint64(file, "time", time(NULL)); + + if ([frames count]) { + FIRCLSFileWriteHashKey(file, "frames"); + FIRCLSFileWriteArrayStart(file); + + for (FIRStackFrame *frame in frames) { + FIRCLSExceptionRecordFrame(file, frame); + } + + FIRCLSFileWriteArrayEnd(file); + } + + FIRCLSFileWriteHashEnd(file); + + FIRCLSFileWriteSectionEnd(file); +} + +void FIRCLSExceptionRecord(FIRCLSExceptionType type, + const char *name, + const char *reason, + NSArray<FIRStackFrame *> *frames, + BOOL attemptDelivery) { + if (!FIRCLSContextIsInitialized()) { + return; + } + + bool native = FIRCLSExceptionIsNative(type); + + FIRCLSSDKLog("Recording an exception structure (%d, %d)\n", attemptDelivery, native); + + // exceptions can happen on multiple threads at the same time + if (native) { + dispatch_sync(_firclsExceptionQueue, ^{ + const char *path = _firclsContext.readonly->exception.path; + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, path, false)) { + FIRCLSSDKLog("Unable to open exception file\n"); + return; + } + + FIRCLSExceptionWrite(&file, type, name, reason, frames); + + // We only want to do this work if we have the expectation that we'll actually crash + FIRCLSHandler(&file, mach_thread_self(), NULL); + + FIRCLSFileClose(&file); + + // disallow immediate delivery for non-native exceptions + if (attemptDelivery) { + FIRCLSHandlerAttemptImmediateDelivery(); + } + }); + } else { + FIRCLSUserLoggingWriteAndCheckABFiles( + &_firclsContext.readonly->logging.customExceptionStorage, + &_firclsContext.writable->logging.activeCustomExceptionPath, ^(FIRCLSFile *file) { + FIRCLSExceptionWrite(file, type, name, reason, frames); + }); + } + + FIRCLSSDKLog("Finished recording an exception structure\n"); +} + +// Ignore this message here, because we know that this call will not leak. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winvalid-noreturn" +void FIRCLSExceptionRaiseTestObjCException(void) { + [NSException raise:@"CrashlyticsTestException" + format:@"This is an Objective-C exception using for testing."]; +} + +void FIRCLSExceptionRaiseTestCppException(void) { + throw "Crashlytics C++ Test Exception"; +} +#pragma clang diagnostic pop + +static const char *FIRCLSExceptionDemangle(const char *symbol) { + return [[FIRCLSDemangleOperation demangleCppSymbol:symbol] UTF8String]; +} + +static void FIRCLSCatchAndRecordActiveException(std::type_info *typeInfo) { + if (!FIRCLSIsValidPointer(typeInfo)) { + FIRCLSSDKLog("Error: invalid parameter\n"); + return; + } + + const char *name = typeInfo->name(); + FIRCLSSDKLog("Recording exception of type '%s'\n", name); + + // This is a funny technique to get the exception object. The inner @try + // has the ability to capture NSException-derived objects. It seems that + // c++ trys can do that in some cases, but I was warned by the WWDC labs + // that there are cases where that will not work (like for NSException subclasses). + try { + @try { + // This could potentially cause a call to std::terminate() if there is actually no active + // exception. + throw; + } @catch (NSException *exception) { +#if TARGET_OS_IPHONE + FIRCLSExceptionRecordNSException(exception); +#else + // There's no need to record this here, because we're going to get + // the value forward to us by AppKit + FIRCLSSDKLog("Skipping ObjC exception at this point\n"); +#endif + } + } catch (const char *exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "const char *", exc, nil, YES); + } catch (const std::string &exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::string", exc.c_str(), nil, YES); + } catch (const std::exception &exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc.what(), nil, + YES); + } catch (const std::exception *exc) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), exc->what(), nil, + YES); + } catch (const std::bad_alloc &exc) { + // it is especially important to avoid demangling in this case, because the expetation at this + // point is that all allocations could fail + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, "std::bad_alloc", exc.what(), nil, YES); + } catch (...) { + FIRCLSExceptionRecord(FIRCLSExceptionTypeCpp, FIRCLSExceptionDemangle(name), "", nil, YES); + } +} + +#pragma mark - Handlers +static void FIRCLSTerminateHandler(void) { + FIRCLSSDKLog("C++ terminate handler invoked\n"); + + void (*handler)(void) = _firclsContext.readonly->exception.originalTerminateHandler; + if (handler == FIRCLSTerminateHandler) { + FIRCLSSDKLog("Error: original handler was set recursively\n"); + handler = NULL; + } + + // Restore pre-existing handler, if any. Do this early, so that + // if std::terminate is called while we are executing here, we do not recurse. + if (handler) { + FIRCLSSDKLog("restoring pre-existing handler\n"); + + // To prevent infinite recursion in this function, check that we aren't resetting the terminate + // handler to the same function again, which would be this function in the event that we can't + // actually change the handler during a terminate. + if (std::set_terminate(handler) == handler) { + FIRCLSSDKLog("handler has already been restored, aborting\n"); + abort(); + } + } + + // we can use typeInfo to record the type of the exception, + // but we must use a catch to get the value + std::type_info *typeInfo = __cxxabiv1::__cxa_current_exception_type(); + if (typeInfo) { + FIRCLSCatchAndRecordActiveException(typeInfo); + } else { + FIRCLSSDKLog("no active exception\n"); + } + + // only do this if there was a pre-existing handler + if (handler) { + FIRCLSSDKLog("invoking pre-existing handler\n"); + handler(); + } + + FIRCLSSDKLog("aborting\n"); + abort(); +} + +void FIRCLSExceptionCheckHandlers(void *delegate) { +#if !TARGET_OS_IPHONE + // Check this on OS X all the time, even if the debugger is attached. This is a common + // source of errors, so we want to be extra verbose in this case. + if (FIRCLSApplicationSharedInstance()) { + if (!FIRCLSIsNSApplicationCrashOnExceptionsEnabled()) { + FIRCLSWarningLog(@"Warning: NSApplicationCrashOnExceptions is not set. This will " + @"result in poor top-level uncaught exception reporting."); + } + } +#endif + + if (_firclsContext.readonly->debuggerAttached) { + return; + } + + void *ptr = NULL; + + ptr = (void *)std::get_terminate(); + if (ptr != FIRCLSTerminateHandler) { + FIRCLSLookupFunctionPointer(ptr, ^(const char *name, const char *lib) { + FIRCLSWarningLog(@"Warning: std::get_terminate is '%s' in '%s'", name, lib); + }); + } + +#if TARGET_OS_IPHONE + ptr = (void *)NSGetUncaughtExceptionHandler(); + if (ptr) { + FIRCLSLookupFunctionPointer(ptr, ^(const char *name, const char *lib) { + FIRCLSWarningLog(@"Warning: NSUncaughtExceptionHandler is '%s' in '%s'", name, lib); + }); + } +#else + if (FIRCLSApplicationSharedInstance() && FIRCLSIsNSApplicationCrashOnExceptionsEnabled()) { + // In this case, we *might* be able to intercept exceptions. But, verify we've still + // swizzled the method. + Method m = FIRCLSGetNSApplicationReportExceptionMethod(); + + if (method_getImplementation(m) != (IMP)FIRCLSNSApplicationReportException) { + FIRCLSWarningLog( + @"Warning: top-level NSApplication-reported exceptions cannot be intercepted"); + } + } +#endif +} + +#pragma mark - AppKit Handling +#if !TARGET_OS_IPHONE +static BOOL FIRCLSIsNSApplicationCrashOnExceptionsEnabled(void) { + return [[NSUserDefaults standardUserDefaults] boolForKey:@"NSApplicationCrashOnExceptions"]; +} + +static Method FIRCLSGetNSApplicationReportExceptionMethod(void) { + return class_getInstanceMethod(NSClassFromString(@"NSApplication"), @selector(reportException:)); +} + +static NSApplicationReportExceptionFunction FIRCLSOriginalNSExceptionReportExceptionFunction(void) { + return (NSApplicationReportExceptionFunction) + _firclsContext.readonly->exception.originalNSApplicationReportException; +} + +void FIRCLSNSApplicationReportException(id self, SEL cmd, NSException *exception) { + FIRCLSExceptionRecordNSException(exception); + + // Call the original implementation + FIRCLSOriginalNSExceptionReportExceptionFunction()(self, cmd, exception); +} + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h new file mode 100644 index 00000000..afc79b5a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h @@ -0,0 +1,26 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <mach/mach.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +__BEGIN_DECLS + +void FIRCLSHandler(FIRCLSFile* file, thread_t crashedThread, void* uapVoid); +void FIRCLSHandlerAttemptImmediateDelivery(void); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m new file mode 100644 index 00000000..1dda16f6 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSHandler.m @@ -0,0 +1,61 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h" + +#include "Crashlytics/Crashlytics/Components/FIRCLSCrashedMarkerFile.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSProcess.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#import "Crashlytics/Crashlytics/Controllers/FIRCLSReportManager_Private.h" + +void FIRCLSHandler(FIRCLSFile* file, thread_t crashedThread, void* uapVoid) { + FIRCLSProcess process; + + FIRCLSProcessInit(&process, crashedThread, uapVoid); + + FIRCLSProcessSuspendAllOtherThreads(&process); + + FIRCLSProcessRecordAllThreads(&process, file); + + FIRCLSProcessRecordRuntimeInfo(&process, file); + // Get dispatch queue and thread names. Note that getting the thread names + // can hang, so let's do that last + FIRCLSProcessRecordDispatchQueueNames(&process, file); + FIRCLSProcessRecordThreadNames(&process, file); + + // this stuff isn't super important, but we can try + FIRCLSProcessRecordStats(&process, file); + FIRCLSHostWriteDiskUsage(file); + + // This is the first common point where various crash handlers call into + // Store a crash file marker to indicate that a crash has occured + FIRCLSCreateCrashedMarkerFile(); + + FIRCLSProcessResumeAllOtherThreads(&process); + + // clean up after ourselves + FIRCLSProcessDestroy(&process); +} + +void FIRCLSHandlerAttemptImmediateDelivery(void) { + // now, attempt to relay the event to the delegate + FIRCLSReportManager* manager = (__bridge id)_firclsContext.readonly->delegate; + + if ([manager respondsToSelector:@selector(potentiallySubmittableCrashOccurred)]) { + [manager potentiallySubmittableCrashOccurred]; + } +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c new file mode 100644 index 00000000..312724c9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.c @@ -0,0 +1,533 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" + +#if CLS_MACH_EXCEPTION_SUPPORTED + +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSProcess.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <errno.h> +#include <mach/mach.h> +#include <pthread.h> +#include <unistd.h> + +#pragma mark Prototypes +static exception_mask_t FIRCLSMachExceptionMask(void); +static void* FIRCLSMachExceptionServer(void* argument); +static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context); +static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message); +static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message); +static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message, + kern_return_t result); +static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context, + exception_mask_t ignoreMask); +static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts, + exception_mask_t mask); +static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message); + +#pragma mark - Initialization +void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context, exception_mask_t ignoreMask) { + if (!FIRCLSUnlinkIfExists(context->path)) { + FIRCLSSDKLog("Unable to reset the mach exception file %s\n", strerror(errno)); + } + + if (!FIRCLSMachExceptionRegister(context, ignoreMask)) { + FIRCLSSDKLog("Unable to register mach exception handler\n"); + return; + } + + if (!FIRCLSMachExceptionThreadStart(context)) { + FIRCLSSDKLog("Unable to start thread\n"); + FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask); + } +} + +void FIRCLSMachExceptionCheckHandlers(void) { + if (_firclsContext.readonly->debuggerAttached) { + return; + } + + // It isn't really critical that this be done, as its extremely uncommon to run into + // preexisting handlers. + // Can use task_get_exception_ports for this. +} + +static exception_mask_t FIRCLSMachExceptionMask(void) { + exception_mask_t mask; + + // EXC_BAD_ACCESS + // EXC_BAD_INSTRUCTION + // EXC_ARITHMETIC + // EXC_EMULATION - non-failure + // EXC_SOFTWARE - non-failure + // EXC_BREAKPOINT - trap instructions, from the debugger and code. Needs special treatment. + // EXC_SYSCALL - non-failure + // EXC_MACH_SYSCALL - non-failure + // EXC_RPC_ALERT - non-failure + // EXC_CRASH - see below + // EXC_RESOURCE - non-failure, happens when a process exceeds a resource limit + // EXC_GUARD - see below + // + // EXC_CRASH is a special kind of exception. It is handled by launchd, and treated special by + // the kernel. Seems that we cannot safely catch it - our handler will never be called. This + // is a confirmed kernel bug. Lacking access to EXC_CRASH means we must use signal handlers to + // cover all types of crashes. + // EXC_GUARD is relatively new, and isn't available on all OS versions. You have to be careful, + // becuase you cannot succesfully register hanlders if there are any unrecognized masks. We've + // dropped support for old OS versions that didn't have EXC_GUARD (iOS 5 and below, macOS 10.6 and + // below) so we always add it now + + mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | + EXC_MASK_BREAKPOINT | EXC_MASK_GUARD; + + return mask; +} + +static bool FIRCLSMachExceptionThreadStart(FIRCLSMachExceptionReadContext* context) { + pthread_attr_t attr; + + if (pthread_attr_init(&attr) != 0) { + FIRCLSSDKLog("pthread_attr_init %s\n", strerror(errno)); + return false; + } + + if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0) { + FIRCLSSDKLog("pthread_attr_setdetachstate %s\n", strerror(errno)); + return false; + } + + // Use to pre-allocate a stack for this thread + // The stack must be page-aligned + if (pthread_attr_setstack(&attr, _firclsContext.readonly->machStack, + CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE) != 0) { + FIRCLSSDKLog("pthread_attr_setstack %s\n", strerror(errno)); + return false; + } + + if (pthread_create(&context->thread, &attr, FIRCLSMachExceptionServer, context) != 0) { + FIRCLSSDKLog("pthread_create %s\n", strerror(errno)); + return false; + } + + pthread_attr_destroy(&attr); + + return true; +} + +exception_mask_t FIRCLSMachExceptionMaskForSignal(int signal) { + switch (signal) { + case SIGTRAP: + return EXC_MASK_BREAKPOINT; + case SIGSEGV: + return EXC_MASK_BAD_ACCESS; + case SIGBUS: + return EXC_MASK_BAD_ACCESS; + case SIGILL: + return EXC_MASK_BAD_INSTRUCTION; + case SIGABRT: + return EXC_MASK_CRASH; + case SIGSYS: + return EXC_MASK_CRASH; + case SIGFPE: + return EXC_MASK_ARITHMETIC; + } + + return 0; +} + +#pragma mark - Message Handling +static void* FIRCLSMachExceptionServer(void* argument) { + FIRCLSMachExceptionReadContext* context = argument; + + pthread_setname_np("com.google.firebase.crashlytics.MachExceptionServer"); + + while (1) { + MachExceptionMessage message; + + // read the exception message + if (!FIRCLSMachExceptionReadMessage(context, &message)) { + break; + } + + // handle it, and possibly forward + kern_return_t result = FIRCLSMachExceptionDispatchMessage(context, &message); + + // and now, reply + if (!FIRCLSMachExceptionReply(context, &message, result)) { + break; + } + } + + FIRCLSSDKLog("Mach exception server thread exiting\n"); + + return NULL; +} + +static bool FIRCLSMachExceptionReadMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message) { + mach_msg_return_t r; + + memset(message, 0, sizeof(MachExceptionMessage)); + + r = mach_msg(&message->head, MACH_RCV_MSG | MACH_RCV_LARGE, 0, sizeof(MachExceptionMessage), + context->port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (r != MACH_MSG_SUCCESS) { + FIRCLSSDKLog("Error receving mach_msg (%d)\n", r); + return false; + } + + FIRCLSSDKLog("Accepted mach exception message\n"); + + return true; +} + +static kern_return_t FIRCLSMachExceptionDispatchMessage(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message) { + FIRCLSSDKLog("Mach exception: 0x%x, count: %d, code: 0x%llx 0x%llx\n", message->exception, + message->codeCnt, message->codeCnt > 0 ? message->code[0] : -1, + message->codeCnt > 1 ? message->code[1] : -1); + + // This will happen if a child process raises an exception, as the exception ports are + // inherited. + if (message->task.name != mach_task_self()) { + FIRCLSSDKLog("Mach exception task mis-match, returning failure\n"); + return KERN_FAILURE; + } + + FIRCLSSDKLog("Unregistering handler\n"); + if (!FIRCLSMachExceptionUnregister(&context->originalPorts, context->mask)) { + FIRCLSSDKLog("Failed to unregister\n"); + return KERN_FAILURE; + } + + FIRCLSSDKLog("Restoring original signal handlers\n"); + if (!FIRCLSSignalSafeInstallPreexistingHandlers(&_firclsContext.readonly->signal)) { + FIRCLSSDKLog("Failed to restore signal handlers\n"); + return KERN_FAILURE; + } + + FIRCLSSDKLog("Recording mach exception\n"); + if (!FIRCLSMachExceptionRecord(context, message)) { + FIRCLSSDKLog("Failed to record mach exception\n"); + return KERN_FAILURE; + } + + return KERN_SUCCESS; +} + +static bool FIRCLSMachExceptionReply(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message, + kern_return_t result) { + MachExceptionReply reply; + mach_msg_return_t r; + + // prepare the reply + reply.head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(message->head.msgh_bits), 0); + reply.head.msgh_remote_port = message->head.msgh_remote_port; + reply.head.msgh_size = (mach_msg_size_t)sizeof(MachExceptionReply); + reply.head.msgh_local_port = MACH_PORT_NULL; + reply.head.msgh_id = message->head.msgh_id + 100; + + reply.NDR = NDR_record; + + reply.retCode = result; + + FIRCLSSDKLog("Sending exception reply\n"); + + // send it + r = mach_msg(&reply.head, MACH_SEND_MSG, reply.head.msgh_size, 0, MACH_PORT_NULL, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + if (r != MACH_MSG_SUCCESS) { + FIRCLSSDKLog("mach_msg reply failed (%d)\n", r); + return false; + } + + FIRCLSSDKLog("Exception reply delivered\n"); + + return true; +} + +#pragma mark - Registration +static bool FIRCLSMachExceptionRegister(FIRCLSMachExceptionReadContext* context, + exception_mask_t ignoreMask) { + mach_port_t task = mach_task_self(); + + kern_return_t kr = mach_port_allocate(task, MACH_PORT_RIGHT_RECEIVE, &context->port); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("Error: mach_port_allocate failed %d\n", kr); + return false; + } + + kr = mach_port_insert_right(task, context->port, context->port, MACH_MSG_TYPE_MAKE_SEND); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("Error: mach_port_insert_right failed %d\n", kr); + mach_port_deallocate(task, context->port); + return false; + } + + // Get the desired mask, which covers all the mach exceptions we are capable of handling, + // but clear out any that are in our ignore list. We do this by ANDing with the bitwise + // negation. Because we are only clearing bits, there's no way to set an incorrect mask + // using ignoreMask. + context->mask = FIRCLSMachExceptionMask() & ~ignoreMask; + + // ORing with MACH_EXCEPTION_CODES will produce 64-bit exception data + kr = task_swap_exception_ports(task, context->mask, context->port, + EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE, + context->originalPorts.masks, &context->originalPorts.count, + context->originalPorts.ports, context->originalPorts.behaviors, + context->originalPorts.flavors); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("Error: task_swap_exception_ports %d\n", kr); + return false; + } + + for (int i = 0; i < context->originalPorts.count; ++i) { + FIRCLSSDKLog("original 0x%x 0x%x 0x%x 0x%x\n", context->originalPorts.ports[i], + context->originalPorts.masks[i], context->originalPorts.behaviors[i], + context->originalPorts.flavors[i]); + } + + return true; +} + +static bool FIRCLSMachExceptionUnregister(FIRCLSMachExceptionOriginalPorts* originalPorts, + exception_mask_t mask) { + kern_return_t kr; + + // Re-register all the old ports. + for (mach_msg_type_number_t i = 0; i < originalPorts->count; ++i) { + // clear the bits from this original mask + mask &= ~originalPorts->masks[i]; + + kr = + task_set_exception_ports(mach_task_self(), originalPorts->masks[i], originalPorts->ports[i], + originalPorts->behaviors[i], originalPorts->flavors[i]); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("unable to restore original port: %d", originalPorts->ports[i]); + } + } + + // Finally, mark any masks we registered for that do not have an original port as unused. + kr = task_set_exception_ports(mach_task_self(), mask, MACH_PORT_NULL, + EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); + if (kr != KERN_SUCCESS) { + FIRCLSSDKLog("unable to unset unregistered mask: 0x%x", mask); + return false; + } + + return true; +} + +#pragma mark - Recording +static void FIRCLSMachExceptionNameLookup(exception_type_t number, + mach_exception_data_type_t code, + const char** name, + const char** codeName) { + if (!name || !codeName) { + return; + } + + *name = NULL; + *codeName = NULL; + + switch (number) { + case EXC_BAD_ACCESS: + *name = "EXC_BAD_ACCESS"; + switch (code) { + case KERN_INVALID_ADDRESS: + *codeName = "KERN_INVALID_ADDRESS"; + break; + case KERN_PROTECTION_FAILURE: + *codeName = "KERN_PROTECTION_FAILURE"; + break; + } + + break; + case EXC_BAD_INSTRUCTION: + *name = "EXC_BAD_INSTRUCTION"; +#if CLS_CPU_X86 + *codeName = "EXC_I386_INVOP"; +#endif + break; + case EXC_ARITHMETIC: + *name = "EXC_ARITHMETIC"; +#if CLS_CPU_X86 + switch (code) { + case EXC_I386_DIV: + *codeName = "EXC_I386_DIV"; + break; + case EXC_I386_INTO: + *codeName = "EXC_I386_INTO"; + break; + case EXC_I386_NOEXT: + *codeName = "EXC_I386_NOEXT"; + break; + case EXC_I386_EXTOVR: + *codeName = "EXC_I386_EXTOVR"; + break; + case EXC_I386_EXTERR: + *codeName = "EXC_I386_EXTERR"; + break; + case EXC_I386_EMERR: + *codeName = "EXC_I386_EMERR"; + break; + case EXC_I386_BOUND: + *codeName = "EXC_I386_BOUND"; + break; + case EXC_I386_SSEEXTERR: + *codeName = "EXC_I386_SSEEXTERR"; + break; + } +#endif + break; + case EXC_BREAKPOINT: + *name = "EXC_BREAKPOINT"; +#if CLS_CPU_X86 + switch (code) { + case EXC_I386_DIVERR: + *codeName = "EXC_I386_DIVERR"; + break; + case EXC_I386_SGLSTP: + *codeName = "EXC_I386_SGLSTP"; + break; + case EXC_I386_NMIFLT: + *codeName = "EXC_I386_NMIFLT"; + break; + case EXC_I386_BPTFLT: + *codeName = "EXC_I386_BPTFLT"; + break; + case EXC_I386_INTOFLT: + *codeName = "EXC_I386_INTOFLT"; + break; + case EXC_I386_BOUNDFLT: + *codeName = "EXC_I386_BOUNDFLT"; + break; + case EXC_I386_INVOPFLT: + *codeName = "EXC_I386_INVOPFLT"; + break; + case EXC_I386_NOEXTFLT: + *codeName = "EXC_I386_NOEXTFLT"; + break; + case EXC_I386_EXTOVRFLT: + *codeName = "EXC_I386_EXTOVRFLT"; + break; + case EXC_I386_INVTSSFLT: + *codeName = "EXC_I386_INVTSSFLT"; + break; + case EXC_I386_SEGNPFLT: + *codeName = "EXC_I386_SEGNPFLT"; + break; + case EXC_I386_STKFLT: + *codeName = "EXC_I386_STKFLT"; + break; + case EXC_I386_GPFLT: + *codeName = "EXC_I386_GPFLT"; + break; + case EXC_I386_PGFLT: + *codeName = "EXC_I386_PGFLT"; + break; + case EXC_I386_EXTERRFLT: + *codeName = "EXC_I386_EXTERRFLT"; + break; + case EXC_I386_ALIGNFLT: + *codeName = "EXC_I386_ALIGNFLT"; + break; + case EXC_I386_ENDPERR: + *codeName = "EXC_I386_ENDPERR"; + break; + case EXC_I386_ENOEXTFLT: + *codeName = "EXC_I386_ENOEXTFLT"; + break; + } +#endif + break; + case EXC_GUARD: + *name = "EXC_GUARD"; + break; + } +} + +static bool FIRCLSMachExceptionRecord(FIRCLSMachExceptionReadContext* context, + MachExceptionMessage* message) { + if (!context || !message) { + return false; + } + + if (FIRCLSContextMarkAndCheckIfCrashed()) { + FIRCLSSDKLog("Error: aborting mach exception handler because crash has already occurred\n"); + exit(1); + return false; + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, context->path, false)) { + FIRCLSSDKLog("Unable to open mach exception file\n"); + return false; + } + + FIRCLSFileWriteSectionStart(&file, "mach_exception"); + + FIRCLSFileWriteHashStart(&file); + + FIRCLSFileWriteHashEntryUint64(&file, "exception", message->exception); + + // record the codes + FIRCLSFileWriteHashKey(&file, "codes"); + FIRCLSFileWriteArrayStart(&file); + for (mach_msg_type_number_t i = 0; i < message->codeCnt; ++i) { + FIRCLSFileWriteArrayEntryUint64(&file, message->code[i]); + } + FIRCLSFileWriteArrayEnd(&file); + + const char* name = NULL; + const char* codeName = NULL; + + FIRCLSMachExceptionNameLookup(message->exception, message->codeCnt > 0 ? message->code[0] : 0, + &name, &codeName); + + FIRCLSFileWriteHashEntryString(&file, "name", name); + FIRCLSFileWriteHashEntryString(&file, "code_name", codeName); + + FIRCLSFileWriteHashEntryUint64(&file, "original_ports", context->originalPorts.count); + FIRCLSFileWriteHashEntryUint64(&file, "time", time(NULL)); + + FIRCLSFileWriteHashEnd(&file); + + FIRCLSFileWriteSectionEnd(&file); + + FIRCLSHandler(&file, message->thread.name, NULL); + + FIRCLSFileClose(&file); + + return true; +} + +#else + +INJECT_STRIP_SYMBOL(cls_mach_exception) + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h new file mode 100644 index 00000000..dadaf27b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSMachException.h @@ -0,0 +1,78 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" + +#pragma once + +#if CLS_MACH_EXCEPTION_SUPPORTED + +#include <mach/mach.h> +#include <pthread.h> +#include <stdbool.h> + +// must be at least PTHREAD_STACK_MIN size +#define CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE (256 * 1024) + +#pragma mark Structures +#pragma pack(push, 4) +typedef struct { + mach_msg_header_t head; + /* start of the kernel processed data */ + mach_msg_body_t msgh_body; + mach_msg_port_descriptor_t thread; + mach_msg_port_descriptor_t task; + /* end of the kernel processed data */ + NDR_record_t NDR; + exception_type_t exception; + mach_msg_type_number_t codeCnt; + mach_exception_data_type_t code[EXCEPTION_CODE_MAX]; + mach_msg_trailer_t trailer; +} MachExceptionMessage; + +typedef struct { + mach_msg_header_t head; + NDR_record_t NDR; + kern_return_t retCode; +} MachExceptionReply; +#pragma pack(pop) + +typedef struct { + mach_msg_type_number_t count; + exception_mask_t masks[EXC_TYPES_COUNT]; + exception_handler_t ports[EXC_TYPES_COUNT]; + exception_behavior_t behaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t flavors[EXC_TYPES_COUNT]; +} FIRCLSMachExceptionOriginalPorts; + +typedef struct { + mach_port_t port; + pthread_t thread; + const char* path; + + exception_mask_t mask; + FIRCLSMachExceptionOriginalPorts originalPorts; +} FIRCLSMachExceptionReadContext; + +#pragma mark - API +void FIRCLSMachExceptionInit(FIRCLSMachExceptionReadContext* context, exception_mask_t ignoreMask); +exception_mask_t FIRCLSMachExceptionMaskForSignal(int signal); + +void FIRCLSMachExceptionCheckHandlers(void); + +#else + +#define CLS_MACH_EXCEPTION_HANDLER_STACK_SIZE 0 + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c new file mode 100644 index 00000000..e96ecfab --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.c @@ -0,0 +1,318 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Handlers/FIRCLSHandler.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <dlfcn.h> +#include <stdlib.h> + +static const int FIRCLSFatalSignals[FIRCLSSignalCount] = {SIGABRT, SIGBUS, SIGFPE, SIGILL, + SIGSEGV, SIGSYS, SIGTRAP}; + +#if CLS_USE_SIGALTSTACK +static void FIRCLSSignalInstallAltStack(FIRCLSSignalReadContext *roContext); +#endif +static void FIRCLSSignalInstallHandlers(FIRCLSSignalReadContext *roContext); +static void FIRCLSSignalHandler(int signal, siginfo_t *info, void *uapVoid); + +void FIRCLSSignalInitialize(FIRCLSSignalReadContext *roContext) { + if (!FIRCLSUnlinkIfExists(roContext->path)) { + FIRCLSSDKLog("Unable to reset the signal log file %s\n", strerror(errno)); + } + +#if CLS_USE_SIGALTSTACK + FIRCLSSignalInstallAltStack(roContext); +#endif + FIRCLSSignalInstallHandlers(roContext); +#if TARGET_IPHONE_SIMULATOR + // prevent the OpenGL stack (by way of OpenGLES.framework/libLLVMContainer.dylib) from installing + // signal handlers that do not chain back + // TODO: I don't believe this is necessary as of recent iOS releases + bool *ptr = dlsym(RTLD_DEFAULT, "_ZN4llvm23DisablePrettyStackTraceE"); + if (ptr) { + *ptr = true; + } +#endif +} + +void FIRCLSSignalEnumerateHandledSignals(void (^block)(int idx, int signal)) { + for (int i = 0; i < FIRCLSSignalCount; ++i) { + block(i, FIRCLSFatalSignals[i]); + } +} + +#if CLS_USE_SIGALTSTACK + +static void FIRCLSSignalInstallAltStack(FIRCLSSignalReadContext *roContext) { + stack_t signalStack; + stack_t originalStack; + + signalStack.ss_sp = _firclsContext.readonly->signalStack; + signalStack.ss_size = CLS_SIGNAL_HANDLER_STACK_SIZE; + signalStack.ss_flags = 0; + + if (sigaltstack(&signalStack, &originalStack) != 0) { + FIRCLSSDKLog("Unable to setup stack %s\n", strerror(errno)); + + return; + } + + roContext->originalStack.ss_sp = NULL; + roContext->originalStack = originalStack; +} + +#endif + +static void FIRCLSSignalInstallHandlers(FIRCLSSignalReadContext *roContext) { + FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) { + struct sigaction action; + struct sigaction previousAction; + + action.sa_sigaction = FIRCLSSignalHandler; + // SA_RESETHAND seems like it would be great, but it doesn't appear to + // work correctly. After taking a signal, causing another identical signal in + // the handler will *not* cause the default handler to be invokved (which should + // terminate the process). I've found some evidence that others have seen this + // behavior on MAC OS X. + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + + sigemptyset(&action.sa_mask); + + previousAction.sa_sigaction = NULL; + if (sigaction(signal, &action, &previousAction) != 0) { + FIRCLSSDKLog("Unable to install handler for %d (%s)\n", signal, strerror(errno)); + } + + // store the last action, so it can be recalled + roContext->originalActions[idx].sa_sigaction = NULL; + + if (previousAction.sa_sigaction) { + roContext->originalActions[idx] = previousAction; + } + }); +} + +void FIRCLSSignalCheckHandlers(void) { + if (_firclsContext.readonly->debuggerAttached) { + return; + } + + FIRCLSSignalEnumerateHandledSignals(^(int idx, int signal) { + struct sigaction previousAction; + Dl_info info; + void *ptr; + + if (sigaction(signal, 0, &previousAction) != 0) { + fprintf(stderr, "Unable to read signal handler\n"); + return; + } + + ptr = previousAction.__sigaction_u.__sa_handler; + const char *signalName = NULL; + const char *codeName = NULL; + + FIRCLSSignalNameLookup(signal, 0, &signalName, &codeName); + + if (ptr == FIRCLSSignalHandler) { + return; + } + + const char *name = NULL; + if (dladdr(ptr, &info) != 0) { + name = info.dli_sname; + } + + fprintf(stderr, + "[Crashlytics] The signal %s has a non-Crashlytics handler (%s). This will interfere " + "with reporting.\n", + signalName, name); + }); +} + +void FIRCLSSignalSafeRemoveHandlers(bool includingAbort) { + for (int i = 0; i < FIRCLSSignalCount; ++i) { + struct sigaction sa; + + if (!includingAbort && (FIRCLSFatalSignals[i] == SIGABRT)) { + continue; + } + + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + + if (sigaction(FIRCLSFatalSignals[i], &sa, NULL) != 0) + FIRCLSSDKLog("Unable to set default handler for %d (%s)\n", i, strerror(errno)); + } +} + +bool FIRCLSSignalSafeInstallPreexistingHandlers(FIRCLSSignalReadContext *roContext) { + bool success; + + FIRCLSSignalSafeRemoveHandlers(true); + +#if CLS_USE_SIGALTSTACK + + // re-install the original stack, if needed + if (roContext->originalStack.ss_sp) { + if (sigaltstack(&roContext->originalStack, 0) != 0) { + FIRCLSSDKLog("Unable to setup stack %s\n", strerror(errno)); + + return false; + } + } + +#endif + + // re-install the original handlers, if any + success = true; + for (int i = 0; i < FIRCLSSignalCount; ++i) { + if (roContext->originalActions[i].sa_sigaction == NULL) { + continue; + } + + if (sigaction(FIRCLSFatalSignals[i], &roContext->originalActions[i], 0) != 0) { + FIRCLSSDKLog("Unable to install handler for %d (%s)\n", i, strerror(errno)); + success = false; + } + } + + return success; +} + +void FIRCLSSignalNameLookup(int number, int code, const char **name, const char **codeName) { + if (!name || !codeName) { + return; + } + + *codeName = NULL; + + switch (number) { + case SIGABRT: + *name = "SIGABRT"; + *codeName = "ABORT"; + break; + case SIGBUS: + *name = "SIGBUS"; + break; + case SIGFPE: + *name = "SIGFPE"; + break; + case SIGILL: + *name = "SIGILL"; + break; + case SIGSEGV: + *name = "SIGSEGV"; + break; + case SIGSYS: + *name = "SIGSYS"; + break; + case SIGTRAP: + *name = "SIGTRAP"; + break; + default: + *name = "UNKNOWN"; + break; + } +} + +static void FIRCLSSignalRecordSignal(int savedErrno, siginfo_t *info, void *uapVoid) { + if (!_firclsContext.readonly) { + return; + } + + if (FIRCLSContextMarkAndCheckIfCrashed()) { + FIRCLSSDKLog("Error: aborting signal handler because crash has already occurred"); + exit(1); + return; + } + + FIRCLSFile file; + + if (!FIRCLSFileInitWithPath(&file, _firclsContext.readonly->signal.path, false)) { + FIRCLSSDKLog("Unable to open signal file\n"); + return; + } + + FIRCLSFileWriteSectionStart(&file, "signal"); + + FIRCLSFileWriteHashStart(&file); + + if (FIRCLSIsValidPointer(info)) { + FIRCLSFileWriteHashEntryUint64(&file, "number", info->si_signo); + FIRCLSFileWriteHashEntryUint64(&file, "code", info->si_code); + FIRCLSFileWriteHashEntryUint64(&file, "address", (uint64_t)info->si_addr); + + const char *name = NULL; + const char *codeName = NULL; + + FIRCLSSignalNameLookup(info->si_signo, info->si_code, &name, &codeName); + + FIRCLSFileWriteHashEntryString(&file, "name", name); + FIRCLSFileWriteHashEntryString(&file, "code_name", codeName); + } + + FIRCLSFileWriteHashEntryUint64(&file, "errno", savedErrno); + FIRCLSFileWriteHashEntryUint64(&file, "time", time(NULL)); + + FIRCLSFileWriteHashEnd(&file); + + FIRCLSFileWriteSectionEnd(&file); + + FIRCLSHandler(&file, mach_thread_self(), uapVoid); + + FIRCLSFileClose(&file); +} + +static void FIRCLSSignalHandler(int signal, siginfo_t *info, void *uapVoid) { + int savedErrno; + sigset_t set; + + // save errno, both because it is interesting, and so we can restore it afterwards + savedErrno = errno; + errno = 0; + + FIRCLSSDKLog("Signal: %d\n", signal); + + // it is important to do this before unmasking signals, otherwise we can get + // called in a loop + FIRCLSSignalSafeRemoveHandlers(true); + + sigfillset(&set); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) { + FIRCLSSDKLog("Unable to unmask signals - we risk infinite recursion here\n"); + } + + // check info and uapVoid, and set them to appropriate values if invalid. This can happen + // if we have been called without the SA_SIGINFO flag set + if (!FIRCLSIsValidPointer(info)) { + info = NULL; + } + + if (!FIRCLSIsValidPointer(uapVoid)) { + uapVoid = NULL; + } + + FIRCLSSignalRecordSignal(savedErrno, info, uapVoid); + + // re-install original handlers + if (_firclsContext.readonly) { + FIRCLSSignalSafeInstallPreexistingHandlers(&_firclsContext.readonly->signal); + } + + // restore errno + errno = savedErrno; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h new file mode 100644 index 00000000..a4533a5c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Handlers/FIRCLSSignal.h @@ -0,0 +1,51 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +#include <signal.h> +#include <stdbool.h> + +#define FIRCLSSignalCount (7) + +// per man sigaltstack, MINSIGSTKSZ is the minimum *overhead* needed to support +// a signal stack. The actual stack size must be larger. Let's pick the recommended +// size. +#if CLS_USE_SIGALTSTACK +#define CLS_SIGNAL_HANDLER_STACK_SIZE (SIGSTKSZ * 2) +#else +#define CLS_SIGNAL_HANDLER_STACK_SIZE 0 +#endif + +typedef struct { + const char* path; + struct sigaction originalActions[FIRCLSSignalCount]; + +#if CLS_USE_SIGALTSTACK + stack_t originalStack; +#endif +} FIRCLSSignalReadContext; + +void FIRCLSSignalInitialize(FIRCLSSignalReadContext* roContext); +void FIRCLSSignalCheckHandlers(void); + +void FIRCLSSignalSafeRemoveHandlers(bool includingAbort); +bool FIRCLSSignalSafeInstallPreexistingHandlers(FIRCLSSignalReadContext* roContext); + +void FIRCLSSignalNameLookup(int number, int code, const char** name, const char** codeName); + +void FIRCLSSignalEnumerateHandledSignals(void (^block)(int idx, int signal)); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h new file mode 100644 index 00000000..84390b85 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// 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. + +#ifndef FIRAEvent_Internal_h +#define FIRAEvent_Internal_h + +#import "Crashlytics/Crashlytics/Helpers/FIRAEvent.h" +#import "Crashlytics/Crashlytics/Helpers/FIRAValue.h" + +NSString* FIRCLSFIRAEventDictionaryToJSON(NSDictionary* eventAsDictionary); + +#endif /* FIRAEvent_Internal_h */ diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m new file mode 100644 index 00000000..0d270635 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.m @@ -0,0 +1,42 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Helpers/FIRAEvent+Internal.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +NSString* FIRCLSFIRAEventDictionaryToJSON(NSDictionary* eventAsDictionary) { + NSError* error = nil; + + if (eventAsDictionary == nil) { + return nil; + } + + if (![NSJSONSerialization isValidJSONObject:eventAsDictionary]) { + FIRCLSSDKLog("Firebase Analytics event is not valid JSON"); + return nil; + } + + NSData* jsonData = [NSJSONSerialization dataWithJSONObject:eventAsDictionary + options:0 + error:&error]; + + if (error == nil) { + NSString* json = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return json; + } else { + FIRCLSSDKLog("Unable to convert Firebase Analytics event to json"); + return nil; + } +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h new file mode 100644 index 00000000..9fcbd660 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAEvent.h @@ -0,0 +1,79 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRAPBEvent; + +/// An application event. +@interface FIRAEvent : NSObject <NSCopying> + +/// Origin of this event (eg "app" or "auto"). +@property(nonatomic, readonly) NSString *origin; + +/// Name of this event. +@property(nonatomic, readonly) NSString *name; + +/// Timestamp of when this event was fired. +@property(nonatomic, readonly) NSTimeInterval timestamp; + +/// Timestamp of the previous time an event with this name was fired, if any. +@property(nonatomic, readonly) NSTimeInterval previousTimestamp; + +/// The event's parameters as {NSString : NSString} or {NSString : NSNumber}. +@property(nonatomic, readonly) NSDictionary *parameters; + +/// Indicates whether the event has the conversion parameter. Setting to YES adds the conversion +/// parameter if not already present. Setting to NO removes the conversion parameter and adds an +/// error. +@property(nonatomic, getter=isConversion) BOOL conversion; + +/// Indicates whether the event has the real-time parameter. Setting to YES adds the real-time +/// parameter if not already present. Setting to NO removes the real-time parameter. +@property(nonatomic, getter=isRealtime) BOOL realtime; + +/// Indicates whether the event has debug parameter. Setting to YES adds the debug parameter if +/// not already present. Setting to NO removes the debug parameter. +@property(nonatomic, getter=isDebug) BOOL debug; + +/// The populated FIRAPBEvent for proto. +@property(nonatomic, readonly) FIRAPBEvent *protoEvent; + +/// Creates an event with the given parameters. Parameters will be copied and normalized. Returns +/// nil if the name does not meet length requirements. +/// If |parameters| contains the "_o" parameter, its value will be overwritten with the value of +/// |origin|. +- (instancetype)initWithOrigin:(NSString *)origin + isPublic:(BOOL)isPublic + name:(NSString *)name + timestamp:(NSTimeInterval)timestamp + previousTimestamp:(NSTimeInterval)previousTimestamp + parameters:(NSDictionary *)parameters NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +/// Returns a new event object with the given previousTimestamp. +- (instancetype)copyWithPreviousTimestamp:(NSTimeInterval)previousTimestamp; + +/// Returns a new event object with the new parameters. +- (instancetype)copyWithParameters:(NSDictionary *)parameters; + +/// Returns YES if all parameters in screenParameters were added to the event object. Returns NO if +/// screenParameters is nil/empty or the event already contains any of the screen parameter keys. +/// Performs internal validation on the screen parameter values and converts them to FIRAValue +/// objects if they aren't already. screenParameters should be a dictionary of +/// { NSString : NSString | NSNumber } or { NSString : FIRAValue }. +- (BOOL)addScreenParameters:(NSDictionary *)screenParameters; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h new file mode 100644 index 00000000..7d10ec30 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRAValue.h @@ -0,0 +1,69 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +typedef NS_ENUM(NSInteger, FIRAValueType) { + kFIRAValueTypeDouble = 0, + kFIRAValueTypeInteger, + kFIRAValueTypeString, +}; + +@interface FIRAValue : NSObject <NSCopying> + +/// The type of the value. +@property(nonatomic, readonly) FIRAValueType valueType; + +#pragma mark - Double type. + +/// Indicates whether the FIRAValue instance is a floating point. +@property(nonatomic, readonly) BOOL isDouble; + +/// Float value. Check valueType to see if this attribute has float value. +@property(nonatomic, readonly) double doubleValue; + +#pragma mark - Integer type. + +/// Indicates whether the FIRAValue instance is an integer. +@property(nonatomic, readonly) BOOL isInt64; + +/// Int64 value. Check valueType to see if this attribute has int64 value. +@property(nonatomic, readonly) int64_t int64Value; + +#pragma mark - String type. + +/// Indicates whether the FIRAValue instance is a string. +@property(nonatomic, readonly) BOOL isString; + +/// String value. Check valueType to see if this attribute has string value. +@property(nonatomic, readonly) NSString *stringValue; + +#pragma mark - Initializers. + +/// Creates a @c FIRAValue if |object| is of type NSString or NSNumber. Returns |object| if it's +/// already a FIRAValue. Returns nil otherwise. ++ (instancetype)valueFromObject:(id)object; + +/// Creates a @c FIRAValue with double value. +- (instancetype)initWithDouble:(double)value; + +/// Creates a @c FIRAValue with int64 value. +- (instancetype)initWithInt64:(int64_t)value; + +/// Creates a @c FIRAValue with string value. +- (instancetype)initWithString:(NSString *)stringValue; + +- (instancetype)init NS_UNAVAILABLE; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c new file mode 100644 index 00000000..84dee840 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.c @@ -0,0 +1,238 @@ +// Copyright 2019 Google +// +// 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. + +#include <stdatomic.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSHost.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <errno.h> +#include <libkern/OSAtomic.h> +#include <mach/vm_map.h> +#include <mach/vm_param.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/mman.h> + +void* FIRCLSAllocatorSafeAllocateFromRegion(FIRCLSAllocationRegion* region, size_t size); + +FIRCLSAllocatorRef FIRCLSAllocatorCreate(size_t writableSpace, size_t readableSpace) { + FIRCLSAllocatorRef allocator; + FIRCLSAllocationRegion writableRegion; + FIRCLSAllocationRegion readableRegion; + size_t allocationSize; + vm_size_t pageSize; + void* buffer; + + // | GUARD | WRITABLE_REGION | GUARD | READABLE_REGION | GUARD | + + pageSize = FIRCLSHostGetPageSize(); + + readableSpace += sizeof(FIRCLSAllocator); // add the space for our allocator itself + + // we can only protect at the page level, so we need all of our regions to be + // exact multples of pages. But, we don't need anything in the special-case of zero. + + writableRegion.size = 0; + if (writableSpace > 0) { + writableRegion.size = ((writableSpace / pageSize) + 1) * pageSize; + } + + readableRegion.size = 0; + if (readableSpace > 0) { + readableRegion.size = ((readableSpace / pageSize) + 1) * pageSize; + } + + // Make one big, continous allocation, adding additional pages for our guards. Note + // that we cannot use malloc (or valloc) in this case, because we need to assert full + // ownership over these allocations. mmap is a much better choice. We also mark these + // pages as MAP_NOCACHE. + allocationSize = writableRegion.size + readableRegion.size + pageSize * 3; + buffer = + mmap(0, allocationSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE | MAP_NOCACHE, -1, 0); + if (buffer == MAP_FAILED) { + FIRCLSSDKLogError("Mapping failed %s\n", strerror(errno)); + return NULL; + } + + // move our cursors into position + writableRegion.cursor = (void*)((uintptr_t)buffer + pageSize); + readableRegion.cursor = (void*)((uintptr_t)buffer + pageSize + writableRegion.size + pageSize); + writableRegion.start = writableRegion.cursor; + readableRegion.start = readableRegion.cursor; + + FIRCLSSDKLogInfo("Mapping: %p %p %p, total: %zu K\n", buffer, writableRegion.start, + readableRegion.start, allocationSize / 1024); + + // protect first guard page + if (mprotect(buffer, pageSize, PROT_NONE) != 0) { + FIRCLSSDKLogError("First guard protection failed %s\n", strerror(errno)); + return NULL; + } + + // middle guard + if (mprotect((void*)((uintptr_t)buffer + pageSize + writableRegion.size), pageSize, PROT_NONE) != + 0) { + FIRCLSSDKLogError("Middle guard protection failed %s\n", strerror(errno)); + return NULL; + } + + // end guard + if (mprotect((void*)((uintptr_t)buffer + pageSize + writableRegion.size + pageSize + + readableRegion.size), + pageSize, PROT_NONE) != 0) { + FIRCLSSDKLogError("Last guard protection failed %s\n", strerror(errno)); + return NULL; + } + + // now, perform our first "allocation", which is to place our allocator into the read-only region + allocator = FIRCLSAllocatorSafeAllocateFromRegion(&readableRegion, sizeof(FIRCLSAllocator)); + + // set up its data structure + allocator->buffer = buffer; + allocator->protectionEnabled = false; + allocator->readableRegion = readableRegion; + allocator->writeableRegion = writableRegion; + + FIRCLSSDKLogDebug("Allocator successfully created %p", allocator); + + return allocator; +} + +void FIRCLSAllocatorDestroy(FIRCLSAllocatorRef allocator) { + if (allocator) { + } +} + +bool FIRCLSAllocatorProtect(FIRCLSAllocatorRef allocator) { + void* address; + + if (!FIRCLSIsValidPointer(allocator)) { + FIRCLSSDKLogError("Invalid allocator"); + return false; + } + + if (allocator->protectionEnabled) { + FIRCLSSDKLogWarn("Write protection already enabled"); + return true; + } + + // This has to be done first + allocator->protectionEnabled = true; + + vm_size_t pageSize = FIRCLSHostGetPageSize(); + + // readable region + address = + (void*)((uintptr_t)allocator->buffer + pageSize + allocator->writeableRegion.size + pageSize); + + return mprotect(address, allocator->readableRegion.size, PROT_READ) == 0; +} + +bool FIRCLSAllocatorUnprotect(FIRCLSAllocatorRef allocator) { + size_t bufferSize; + + if (!allocator) { + return false; + } + + vm_size_t pageSize = FIRCLSHostGetPageSize(); + + bufferSize = (uintptr_t)allocator->buffer + pageSize + allocator->writeableRegion.size + + pageSize + allocator->readableRegion.size + pageSize; + + allocator->protectionEnabled = + !(mprotect(allocator->buffer, bufferSize, PROT_READ | PROT_WRITE) == 0); + + return allocator->protectionEnabled; +} + +void* FIRCLSAllocatorSafeAllocateFromRegion(FIRCLSAllocationRegion* region, size_t size) { + void* newCursor; + void* originalCursor; + + // Here's the idea + // - read the current cursor + // - compute what our new cursor should be + // - attempt a swap + // if the swap fails, some other thread has modified stuff, and we have to start again + // if the swap works, everything has been updated correctly and we are done + do { + originalCursor = region->cursor; + + // this shouldn't happen unless we make a mistake with our size pre-computations + if ((uintptr_t)originalCursor - (uintptr_t)region->start + size > region->size) { + FIRCLSSDKLog("Unable to allocate sufficient memory, falling back to malloc\n"); + void* ptr = malloc(size); + if (!ptr) { + FIRCLSSDKLog("Unable to malloc in FIRCLSAllocatorSafeAllocateFromRegion\n"); + return NULL; + } + return ptr; + } + + newCursor = (void*)((uintptr_t)originalCursor + size); + } while (!atomic_compare_exchange_strong(®ion->cursor, &originalCursor, newCursor)); + + return originalCursor; +} + +void* FIRCLSAllocatorSafeAllocate(FIRCLSAllocatorRef allocator, + size_t size, + FIRCLSAllocationType type) { + FIRCLSAllocationRegion* region; + + if (!allocator) { + // fall back to malloc in this case + FIRCLSSDKLog("Allocator invalid, falling back to malloc\n"); + void* ptr = malloc(size); + if (!ptr) { + FIRCLSSDKLog("Unable to malloc in FIRCLSAllocatorSafeAllocate\n"); + return NULL; + } + return ptr; + } + + if (allocator->protectionEnabled) { + FIRCLSSDKLog("Allocator already protected, falling back to malloc\n"); + void* ptr = malloc(size); + if (!ptr) { + FIRCLSSDKLog("Unable to malloc in FIRCLSAllocatorSafeAllocate\n"); + return NULL; + } + return ptr; + } + + switch (type) { + case CLS_READONLY: + region = &allocator->readableRegion; + break; + case CLS_READWRITE: + region = &allocator->writeableRegion; + break; + default: + return NULL; + } + + return FIRCLSAllocatorSafeAllocateFromRegion(region, size); +} + +void FIRCLSAllocatorFree(FIRCLSAllocatorRef allocator, void* ptr) { + if (!allocator) { + free(ptr); + } + + // how do we do deallocations? +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h new file mode 100644 index 00000000..ae7a8a4c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSAllocate.h @@ -0,0 +1,48 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" + +#pragma once + +#include <stdbool.h> +#include <sys/types.h> + +typedef enum { CLS_READONLY = 0, CLS_READWRITE = 1 } FIRCLSAllocationType; + +typedef struct { + size_t size; + void* start; + _Atomic(void*) volatile cursor; +} FIRCLSAllocationRegion; + +typedef struct { + void* buffer; + bool protectionEnabled; + FIRCLSAllocationRegion writeableRegion; + FIRCLSAllocationRegion readableRegion; +} FIRCLSAllocator; +typedef FIRCLSAllocator* FIRCLSAllocatorRef; + +FIRCLSAllocatorRef FIRCLSAllocatorCreate(size_t writableSpace, size_t readableSpace); +void FIRCLSAllocatorDestroy(FIRCLSAllocatorRef allocator); + +bool FIRCLSAllocatorProtect(FIRCLSAllocatorRef allocator); +bool FIRCLSAllocatorUnprotect(FIRCLSAllocatorRef allocator); + +void* FIRCLSAllocatorSafeAllocate(FIRCLSAllocatorRef allocator, + size_t size, + FIRCLSAllocationType type); +const char* FIRCLSAllocatorSafeStrdup(FIRCLSAllocatorRef allocator, const char* string); +void FIRCLSAllocatorFree(FIRCLSAllocatorRef allocator, void* ptr); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h new file mode 100644 index 00000000..9f57e532 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h @@ -0,0 +1,81 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <TargetConditionals.h> + +// macro trickiness +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) +#define CONCAT_EXPANDED(a, b) a##b +#define CONCAT(a, b) CONCAT_EXPANDED(a, b) + +// These macros generate a function to force a symbol for the containing .o, to work around an issue +// where strip will not strip debug information without a symbol to strip. +#define DUMMY_FUNCTION_NAME(x) CONCAT(fircls_strip_this_, x) +#define INJECT_STRIP_SYMBOL(x) \ + void DUMMY_FUNCTION_NAME(x)(void) { \ + } + +// These make some target os types available to previous versions of xcode that do not yet have them +// in their SDKs +#ifndef TARGET_OS_IOS +#define TARGET_OS_IOS TARGET_OS_IPHONE +#endif + +#ifndef TARGET_OS_WATCH +#define TARGET_OS_WATCH 0 +#endif + +#ifndef TARGET_OS_TV +#define TARGET_OS_TV 0 +#endif + +// These help compile based on availability of technologies/frameworks. +#define CLS_TARGET_OS_OSX (TARGET_OS_MAC && !TARGET_OS_IPHONE) +#define CLS_TARGET_OS_HAS_UIKIT (TARGET_OS_IOS || TARGET_OS_TV) + +#define CLS_SDK_DISPLAY_VERSION STR(DISPLAY_VERSION) + +#define CLS_SDK_GENERATOR_NAME (STR(CLS_SDK_NAME) "/" CLS_SDK_DISPLAY_VERSION) + +// arch definitions +#if defined(__arm__) || defined(__arm64__) || defined(__arm64e__) +#include <arm/arch.h> +#endif + +#if defined(__arm__) +#define CLS_CPU_ARM 1 +#endif +#if defined(__arm64__) || defined(__arm64e__) +#define CLS_CPU_ARM64 1 +#endif +#if defined(__ARM_ARCH_7S__) +#define CLS_CPU_ARMV7S 1 +#endif +#if defined(_ARM_ARCH_7) +#define CLS_CPU_ARMV7 1 +#endif +#if defined(_ARM_ARCH_6) +#define CLS_CPU_ARMV6 1 +#endif +#if defined(__i386__) +#define CLS_CPU_I386 1 +#endif +#if defined(__x86_64__) +#define CLS_CPU_X86_64 1 +#endif +#define CLS_CPU_X86 (CLS_CPU_I386 || CLS_CPU_X86_64) +#define CLS_CPU_64BIT (CLS_CPU_X86_64 || CLS_CPU_ARM64) diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h new file mode 100644 index 00000000..098833f6 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRCLSSettings; +@protocol FIRAnalyticsInterop; +@protocol FIRAnalyticsInteropListener; + +@interface FIRCLSFCRAnalytics : NSObject + +/** Logs a Crashlytics crash session in Firebase Analytics. + * @param crashTimeStamp The time stamp of the crash to be logged. + */ ++ (void)logCrashWithTimeStamp:(NSTimeInterval)crashTimeStamp + toAnalytics:(id<FIRAnalyticsInterop>)analytics; + ++ (void)registerEventListener:(id<FIRAnalyticsInteropListener>)eventListener + toAnalytics:(id<FIRAnalyticsInterop>)analytics; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.m new file mode 100644 index 00000000..0c47d3ff --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.m @@ -0,0 +1,78 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFCRAnalytics.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" + +#import "Interop/Analytics/Public/FIRAnalyticsInterop.h" + +// Origin for events and user properties generated by Crashlytics. +static NSString *const kFIREventOriginCrash = @"clx"; + +// App exception event name. +static NSString *const kFIREventAppException = @"_ae"; + +// Timestamp key for the event payload. +static NSString *const kFIRParameterTimestamp = @"timestamp"; + +// Fatal key for the event payload. +static NSString *const kFIRParameterFatal = @"fatal"; + +FOUNDATION_STATIC_INLINE NSNumber *timeIntervalInMillis(NSTimeInterval timeInterval) { + return @(llrint(timeInterval * 1000.0)); +} + +@implementation FIRCLSFCRAnalytics + ++ (void)logCrashWithTimeStamp:(NSTimeInterval)crashTimeStamp + toAnalytics:(id<FIRAnalyticsInterop>)analytics { + if (analytics == nil) { + return; + } + + FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports:Event", "Sending event."); + NSDictionary *params = [self buildLogParamsFromCrash:crashTimeStamp]; + [analytics logEventWithOrigin:kFIREventOriginCrash name:kFIREventAppException parameters:params]; +} + ++ (void)registerEventListener:(id<FIRAnalyticsInteropListener>)eventListener + toAnalytics:(id<FIRAnalyticsInterop>)analytics { + if (analytics == nil) { + return; + } + + [analytics registerAnalyticsListener:eventListener withOrigin:kFIREventOriginCrash]; + + FIRCLSDeveloperLog(@"Crashlytics:Crash:Reports:Event", + "Registered Firebase Analytics event listener"); +} + +/** + * Builds a dictionary of params to be sent to Analytics using the crash object. + * + * @param crashTimeStamp The time stamp of the crash to be logged. + * + * @return An NSDictionary containing the time the crash occured and the fatal + * flag to be fed into Firebase Analytics. + */ ++ (NSDictionary *)buildLogParamsFromCrash:(NSTimeInterval)crashTimeStamp { + return @{ + kFIRParameterTimestamp : timeIntervalInMillis(crashTimeStamp), + kFIRParameterFatal : @(INT64_C(1)) + }; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h new file mode 100644 index 00000000..ba61233b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" + +#define CLS_MEMORY_PROTECTION_ENABLED 1 +#define CLS_COMPACT_UNWINDED_ENABLED 1 +#define CLS_DWARF_UNWINDING_ENABLED 1 + +#define CLS_USE_SIGALTSTACK (!TARGET_OS_WATCH && !TARGET_OS_TV) +#define CLS_CAN_SUSPEND_THREADS !TARGET_OS_WATCH +#define CLS_MACH_EXCEPTION_SUPPORTED (!TARGET_OS_WATCH && !TARGET_OS_TV) + +#define CLS_COMPACT_UNWINDING_SUPPORTED \ + ((CLS_CPU_I386 || CLS_CPU_X86_64 || CLS_CPU_ARM64) && CLS_COMPACT_UNWINDED_ENABLED) + +#define CLS_DWARF_UNWINDING_SUPPORTED \ + (CLS_COMPACT_UNWINDING_SUPPORTED && CLS_DWARF_UNWINDING_ENABLED) diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h new file mode 100644 index 00000000..1714ac12 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.h @@ -0,0 +1,109 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> +#include <sys/cdefs.h> + +// Required for 1P builds +#include <stddef.h> +#include <sys/types.h> +#include <unistd.h> + +#if defined(__OBJC__) +#import <Foundation/Foundation.h> +#endif + +__BEGIN_DECLS + +typedef struct { + int fd; + int collectionDepth; + bool needComma; + + bool bufferWrites; + char* writeBuffer; + size_t writeBufferLength; + + off_t writtenLength; +} FIRCLSFile; +typedef FIRCLSFile* FIRCLSFileRef; + +#define CLS_FILE_MAX_STRING_LENGTH (10240) +#define CLS_FILE_HEX_BUFFER \ + (32) // must be at least 2, and should be even (to account for 2 chars per hex value) +#define CLS_FILE_MAX_WRITE_ATTEMPTS (50) + +extern const size_t FIRCLSWriteBufferLength; + +// make sure to stop work if either FIRCLSFileInit... method returns false, because the FIRCLSFile +// struct will contain garbage data! +bool FIRCLSFileInitWithPath(FIRCLSFile* file, const char* path, bool bufferWrites); +bool FIRCLSFileInitWithPathMode(FIRCLSFile* file, + const char* path, + bool appendMode, + bool bufferWrites); + +void FIRCLSFileFlushWriteBuffer(FIRCLSFile* file); +bool FIRCLSFileClose(FIRCLSFile* file); +bool FIRCLSFileCloseWithOffset(FIRCLSFile* file, off_t* finalSize); +bool FIRCLSFileIsOpen(FIRCLSFile* file); + +bool FIRCLSFileLoopWithWriteBlock(const void* buffer, + size_t length, + ssize_t (^writeBlock)(const void* partialBuffer, + size_t partialLength)); +bool FIRCLSFileWriteWithRetries(int fd, const void* buffer, size_t length); + +// writing +void FIRCLSFileWriteSectionStart(FIRCLSFile* file, const char* name); +void FIRCLSFileWriteSectionEnd(FIRCLSFile* file); + +void FIRCLSFileWriteHashStart(FIRCLSFile* file); +void FIRCLSFileWriteHashEnd(FIRCLSFile* file); +void FIRCLSFileWriteHashKey(FIRCLSFile* file, const char* key); +void FIRCLSFileWriteHashEntryUint64(FIRCLSFile* file, const char* key, uint64_t value); +void FIRCLSFileWriteHashEntryInt64(FIRCLSFile* file, const char* key, int64_t value); +void FIRCLSFileWriteHashEntryString(FIRCLSFile* file, const char* key, const char* value); +#if defined(__OBJC__) +void FIRCLSFileWriteHashEntryNSString(FIRCLSFile* file, const char* key, NSString* string); +void FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(FIRCLSFile* file, + const char* key, + NSString* string); +#endif +void FIRCLSFileWriteHashEntryHexEncodedString(FIRCLSFile* file, const char* key, const char* value); +void FIRCLSFileWriteHashEntryBoolean(FIRCLSFile* file, const char* key, bool value); + +void FIRCLSFileWriteArrayStart(FIRCLSFile* file); +void FIRCLSFileWriteArrayEnd(FIRCLSFile* file); +void FIRCLSFileWriteArrayEntryUint64(FIRCLSFile* file, uint64_t value); +void FIRCLSFileWriteArrayEntryString(FIRCLSFile* file, const char* value); +void FIRCLSFileWriteArrayEntryHexEncodedString(FIRCLSFile* file, const char* value); + +void FIRCLSFileFDWriteUInt64(int fd, uint64_t number, bool hex); +void FIRCLSFileFDWriteInt64(int fd, int64_t number); +void FIRCLSFileWriteUInt64(FIRCLSFile* file, uint64_t number, bool hex); +void FIRCLSFileWriteInt64(FIRCLSFile* file, int64_t number); + +#if defined(__OBJC__) && TARGET_OS_MAC +NSArray* FIRCLSFileReadSections(const char* path, + bool deleteOnFailure, + NSObject* (^transformer)(id obj)); +NSString* FIRCLSFileHexEncodeString(const char* string); +NSString* FIRCLSFileHexDecodeString(const char* string); +#endif + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.m new file mode 100644 index 00000000..84ba8f4b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSFile.m @@ -0,0 +1,702 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#include "Crashlytics/Shared/FIRCLSByteUtility.h" + +#if TARGET_OS_MAC +#include <Foundation/Foundation.h> +#endif + +#include <sys/stat.h> + +#include <stdio.h> +#include <string.h> + +#include <unistd.h> + +// uint64_t should only have max 19 chars in base 10, and less in base 16 +static const size_t FIRCLSUInt64StringBufferLength = 21; +static const size_t FIRCLSStringBufferLength = 16; +const size_t FIRCLSWriteBufferLength = 1000; + +static bool FIRCLSFileInit(FIRCLSFile* file, int fdm, bool appendMode, bool bufferWrites); + +static void FIRCLSFileWriteToFileDescriptorOrBuffer(FIRCLSFile* file, + const char* string, + size_t length); +static void FIRCLSFileWriteToBuffer(FIRCLSFile* file, const char* string, size_t length); +static void FIRCLSFileWriteToFileDescriptor(FIRCLSFile* file, const char* string, size_t length); + +short FIRCLSFilePrepareUInt64(char* buffer, uint64_t number, bool hex); + +static void FIRCLSFileWriteString(FIRCLSFile* file, const char* string); +static void FIRCLSFileWriteHexEncodedString(FIRCLSFile* file, const char* string); +static void FIRCLSFileWriteBool(FIRCLSFile* file, bool value); + +static void FIRCLSFileWriteCollectionStart(FIRCLSFile* file, const char openingChar); +static void FIRCLSFileWriteCollectionEnd(FIRCLSFile* file, const char closingChar); +static void FIRCLSFileWriteColletionEntryProlog(FIRCLSFile* file); +static void FIRCLSFileWriteColletionEntryEpilog(FIRCLSFile* file); + +#define CLS_FILE_DEBUG_LOGGING 0 + +#pragma mark - File Structure +static bool FIRCLSFileInit(FIRCLSFile* file, int fd, bool appendMode, bool bufferWrites) { + if (!file) { + FIRCLSSDKLog("Error: file is null\n"); + return false; + } + + if (fd < 0) { + FIRCLSSDKLog("Error: file descriptor invalid\n"); + return false; + } + + memset(file, 0, sizeof(FIRCLSFile)); + + file->fd = fd; + + file->bufferWrites = bufferWrites; + if (bufferWrites) { + file->writeBuffer = malloc(FIRCLSWriteBufferLength * sizeof(char)); + if (!file->writeBuffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSFileInit"); + return false; + } + + file->writeBufferLength = 0; + } + + file->writtenLength = 0; + if (appendMode) { + struct stat fileStats; + fstat(fd, &fileStats); + off_t currentFileSize = fileStats.st_size; + if (currentFileSize > 0) { + file->writtenLength += currentFileSize; + } + } + + return true; +} + +bool FIRCLSFileInitWithPath(FIRCLSFile* file, const char* path, bool bufferWrites) { + return FIRCLSFileInitWithPathMode(file, path, true, bufferWrites); +} + +bool FIRCLSFileInitWithPathMode(FIRCLSFile* file, + const char* path, + bool appendMode, + bool bufferWrites) { + if (!file) { + FIRCLSSDKLog("Error: file is null\n"); + return false; + } + + int mask = O_WRONLY | O_CREAT; + + if (appendMode) { + mask |= O_APPEND; + } else { + mask |= O_TRUNC; + } + + // make sure to call FIRCLSFileInit no matter what + int fd = -1; + if (path) { +#if TARGET_OS_IPHONE + /* + * data-protected non-portable open(2) : + * int open_dprotected_np(user_addr_t path, int flags, int class, int dpflags, int mode) + */ + fd = open_dprotected_np(path, mask, 4, 0, 0644); +#else + fd = open(path, mask, 0644); +#endif + + if (fd < 0) { + FIRCLSSDKLog("Error: Unable to open file %s\n", strerror(errno)); + } + } + + return FIRCLSFileInit(file, fd, appendMode, bufferWrites); +} + +bool FIRCLSFileClose(FIRCLSFile* file) { + return FIRCLSFileCloseWithOffset(file, NULL); +} + +bool FIRCLSFileCloseWithOffset(FIRCLSFile* file, off_t* finalSize) { + if (!FIRCLSIsValidPointer(file)) { + return false; + } + + if (file->bufferWrites && FIRCLSIsValidPointer(file->writeBuffer)) { + if (file->writeBufferLength > 0) { + FIRCLSFileFlushWriteBuffer(file); + } + free(file->writeBuffer); + } + + if (FIRCLSIsValidPointer(finalSize)) { + *finalSize = file->writtenLength; + } + + if (close(file->fd) != 0) { + FIRCLSSDKLog("Error: Unable to close file %s\n", strerror(errno)); + return false; + } + + memset(file, 0, sizeof(FIRCLSFile)); + file->fd = -1; + + return true; +} + +bool FIRCLSFileIsOpen(FIRCLSFile* file) { + if (!FIRCLSIsValidPointer(file)) { + return false; + } + + return file->fd > -1; +} + +#pragma mark - Core Writing API +void FIRCLSFileFlushWriteBuffer(FIRCLSFile* file) { + if (!FIRCLSIsValidPointer(file)) { + return; + } + + if (!file->bufferWrites) { + return; + } + + FIRCLSFileWriteToFileDescriptor(file, file->writeBuffer, file->writeBufferLength); + file->writeBufferLength = 0; +} + +static void FIRCLSFileWriteToFileDescriptorOrBuffer(FIRCLSFile* file, + const char* string, + size_t length) { + if (file->bufferWrites) { + if (file->writeBufferLength + length > FIRCLSWriteBufferLength - 1) { + // fill remaining space in buffer + size_t remainingSpace = FIRCLSWriteBufferLength - file->writeBufferLength - 1; + FIRCLSFileWriteToBuffer(file, string, remainingSpace); + FIRCLSFileFlushWriteBuffer(file); + + // write remainder of string to newly-emptied buffer + size_t remainingLength = length - remainingSpace; + FIRCLSFileWriteToFileDescriptorOrBuffer(file, string + remainingSpace, remainingLength); + } else { + FIRCLSFileWriteToBuffer(file, string, length); + } + } else { + FIRCLSFileWriteToFileDescriptor(file, string, length); + } +} + +static void FIRCLSFileWriteToFileDescriptor(FIRCLSFile* file, const char* string, size_t length) { + if (!FIRCLSFileWriteWithRetries(file->fd, string, length)) { + return; + } + + file->writtenLength += length; +} + +// Beware calling this method directly: it will truncate the input string if it's longer +// than the remaining space in the buffer. It's safer to call through +// FIRCLSFileWriteToFileDescriptorOrBuffer. +static void FIRCLSFileWriteToBuffer(FIRCLSFile* file, const char* string, size_t length) { + size_t writeLength = length; + if (file->writeBufferLength + writeLength > FIRCLSWriteBufferLength - 1) { + writeLength = FIRCLSWriteBufferLength - file->writeBufferLength - 1; + } + strncpy(file->writeBuffer + file->writeBufferLength, string, writeLength); + file->writeBufferLength += writeLength; + file->writeBuffer[file->writeBufferLength] = '\0'; +} + +bool FIRCLSFileLoopWithWriteBlock(const void* buffer, + size_t length, + ssize_t (^writeBlock)(const void* buf, size_t len)) { + for (size_t count = 0; length > 0 && count < CLS_FILE_MAX_WRITE_ATTEMPTS; ++count) { + // try to write all that is left + ssize_t ret = writeBlock(buffer, length); + if (ret >= 0 && ret == length) { + return true; + } + + // Write was unsuccessful (out of space, etc) + if (ret < 0) { + return false; + } + + // We wrote more bytes than we expected, abort + if (ret > length) { + return false; + } + + // wrote a portion of the data, adjust and keep trying + if (ret > 0) { + length -= ret; + buffer += ret; + continue; + } + + // return value is <= 0, which is an error + break; + } + + return false; +} + +bool FIRCLSFileWriteWithRetries(int fd, const void* buffer, size_t length) { + return FIRCLSFileLoopWithWriteBlock(buffer, length, + ^ssize_t(const void* partialBuffer, size_t partialLength) { + return write(fd, partialBuffer, partialLength); + }); +} + +#pragma mark - Strings + +static void FIRCLSFileWriteUnbufferedStringWithSuffix(FIRCLSFile* file, + const char* string, + size_t length, + char suffix) { + char suffixBuffer[2]; + + // collaspe the quote + suffix into one single write call, for a small performance win + suffixBuffer[0] = '"'; + suffixBuffer[1] = suffix; + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\"", 1); + FIRCLSFileWriteToFileDescriptorOrBuffer(file, string, length); + FIRCLSFileWriteToFileDescriptorOrBuffer(file, suffixBuffer, suffix == 0 ? 1 : 2); +} + +static void FIRCLSFileWriteStringWithSuffix(FIRCLSFile* file, + const char* string, + size_t length, + char suffix) { + // 2 for quotes, 1 for suffix (if present) and 1 more for null character + const size_t maxStringSize = FIRCLSStringBufferLength - (suffix == 0 ? 3 : 4); + + if (length >= maxStringSize) { + FIRCLSFileWriteUnbufferedStringWithSuffix(file, string, length, suffix); + return; + } + + // we are trying to achieve this in one write call + // <"><string contents><"><suffix> + + char buffer[FIRCLSStringBufferLength]; + + buffer[0] = '"'; + + strncpy(buffer + 1, string, length); + + buffer[length + 1] = '"'; + length += 2; + + if (suffix) { + buffer[length] = suffix; + length += 1; + } + + // Always add the terminator. strncpy above would copy the terminator, if we supplied length + 1, + // but since we do this suffix adjustment here, it's easier to just fix it up in both cases. + buffer[length + 1] = 0; + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, buffer, length); +} + +void FIRCLSFileWriteString(FIRCLSFile* file, const char* string) { + if (!string) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "null", 4); + return; + } + + FIRCLSFileWriteStringWithSuffix(file, string, strlen(string), 0); +} + +void FIRCLSFileWriteHexEncodedString(FIRCLSFile* file, const char* string) { + if (!file) { + return; + } + + if (!string) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "null", 4); + return; + } + + char buffer[CLS_FILE_HEX_BUFFER]; + + memset(buffer, 0, sizeof(buffer)); + + size_t length = strlen(string); + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\"", 1); + + int bufferIndex = 0; + for (int i = 0; i < length; ++i) { + FIRCLSHexFromByte(string[i], &buffer[bufferIndex]); + + bufferIndex += 2; // 1 char => 2 hex values at a time + + // we can continue only if we have enough space for two more hex + // characters *and* a terminator. So, we need three total chars + // of space + if (bufferIndex >= CLS_FILE_HEX_BUFFER) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, buffer, CLS_FILE_HEX_BUFFER); + bufferIndex = 0; + } + } + + // Copy the remainder, which could even be the entire string, if it + // fit into the buffer completely. Be careful with bounds checking here. + // The string needs to be non-empty, and we have to have copied at least + // one pair of hex characters in. + if (bufferIndex > 0 && length > 0) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, buffer, bufferIndex); + } + + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\"", 1); +} + +#pragma mark - Integers +void FIRCLSFileWriteUInt64(FIRCLSFile* file, uint64_t number, bool hex) { + char buffer[FIRCLSUInt64StringBufferLength]; + short i = FIRCLSFilePrepareUInt64(buffer, number, hex); + char* beginning = &buffer[i]; // Write from a pointer to the begining of the string. + FIRCLSFileWriteToFileDescriptorOrBuffer(file, beginning, strlen(beginning)); +} + +void FIRCLSFileFDWriteUInt64(int fd, uint64_t number, bool hex) { + char buffer[FIRCLSUInt64StringBufferLength]; + short i = FIRCLSFilePrepareUInt64(buffer, number, hex); + char* beginning = &buffer[i]; // Write from a pointer to the begining of the string. + FIRCLSFileWriteWithRetries(fd, beginning, strlen(beginning)); +} + +void FIRCLSFileWriteInt64(FIRCLSFile* file, int64_t number) { + if (number < 0) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "-", 1); + number *= -1; // make it positive + } + + FIRCLSFileWriteUInt64(file, number, false); +} + +void FIRCLSFileFDWriteInt64(int fd, int64_t number) { + if (number < 0) { + FIRCLSFileWriteWithRetries(fd, "-", 1); + number *= -1; // make it positive + } + + FIRCLSFileFDWriteUInt64(fd, number, false); +} + +short FIRCLSFilePrepareUInt64(char* buffer, uint64_t number, bool hex) { + uint32_t base = hex ? 16 : 10; + + // zero it out, which will add a terminator + memset(buffer, 0, FIRCLSUInt64StringBufferLength); + + // TODO: look at this closer + // I'm pretty sure there is a bug in this code that + // can result in numbers with leading zeros. Technically, + // those are not valid json. + + // Set current index. + short i = FIRCLSUInt64StringBufferLength - 1; + + // Loop through filling in the chars from the end. + do { + char value = number % base + '0'; + if (value > '9') { + value += 'a' - '9' - 1; + } + + buffer[--i] = value; + } while ((number /= base) > 0 && i > 0); + + // returns index pointing to the beginning of the string. + return i; +} + +void FIRCLSFileWriteBool(FIRCLSFile* file, bool value) { + if (value) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "true", 4); + } else { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "false", 5); + } +} + +void FIRCLSFileWriteSectionStart(FIRCLSFile* file, const char* name) { + FIRCLSFileWriteHashStart(file); + FIRCLSFileWriteHashKey(file, name); +} + +void FIRCLSFileWriteSectionEnd(FIRCLSFile* file) { + FIRCLSFileWriteHashEnd(file); + FIRCLSFileWriteToFileDescriptorOrBuffer(file, "\n", 1); +} + +void FIRCLSFileWriteCollectionStart(FIRCLSFile* file, const char openingChar) { + char string[2]; + + string[0] = ','; + string[1] = openingChar; + + if (file->needComma) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, string, 2); // write the seperator + opening char + } else { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, &string[1], 1); // write only the opening char + } + + file->collectionDepth++; + + file->needComma = false; +} + +void FIRCLSFileWriteCollectionEnd(FIRCLSFile* file, const char closingChar) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, &closingChar, 1); + + if (file->collectionDepth <= 0) { + // FIRCLSSafeLog("Collection depth invariant violated\n"); + return; + } + + file->collectionDepth--; + + file->needComma = file->collectionDepth > 0; +} + +void FIRCLSFileWriteColletionEntryProlog(FIRCLSFile* file) { + if (file->needComma) { + FIRCLSFileWriteToFileDescriptorOrBuffer(file, ",", 1); + } +} + +void FIRCLSFileWriteColletionEntryEpilog(FIRCLSFile* file) { + file->needComma = true; +} + +void FIRCLSFileWriteHashStart(FIRCLSFile* file) { + FIRCLSFileWriteCollectionStart(file, '{'); +} + +void FIRCLSFileWriteHashEnd(FIRCLSFile* file) { + FIRCLSFileWriteCollectionEnd(file, '}'); +} + +void FIRCLSFileWriteHashKey(FIRCLSFile* file, const char* key) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteStringWithSuffix(file, key, strlen(key), ':'); + + file->needComma = false; +} + +void FIRCLSFileWriteHashEntryUint64(FIRCLSFile* file, const char* key, uint64_t value) { + // no prolog needed because it comes from the key + + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteUInt64(file, value, false); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryInt64(FIRCLSFile* file, const char* key, int64_t value) { + // prolog from key + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteInt64(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryString(FIRCLSFile* file, const char* key, const char* value) { + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryNSString(FIRCLSFile* file, const char* key, NSString* string) { + FIRCLSFileWriteHashEntryString(file, key, [string UTF8String]); +} + +void FIRCLSFileWriteHashEntryNSStringUnlessNilOrEmpty(FIRCLSFile* file, + const char* key, + NSString* string) { + if ([string length] > 0) { + FIRCLSFileWriteHashEntryString(file, key, [string UTF8String]); + } +} + +void FIRCLSFileWriteHashEntryHexEncodedString(FIRCLSFile* file, + const char* key, + const char* value) { + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteHexEncodedString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteHashEntryBoolean(FIRCLSFile* file, const char* key, bool value) { + FIRCLSFileWriteHashKey(file, key); + FIRCLSFileWriteBool(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteArrayStart(FIRCLSFile* file) { + FIRCLSFileWriteCollectionStart(file, '['); +} + +void FIRCLSFileWriteArrayEnd(FIRCLSFile* file) { + FIRCLSFileWriteCollectionEnd(file, ']'); +} + +void FIRCLSFileWriteArrayEntryUint64(FIRCLSFile* file, uint64_t value) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteUInt64(file, value, false); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteArrayEntryString(FIRCLSFile* file, const char* value) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +void FIRCLSFileWriteArrayEntryHexEncodedString(FIRCLSFile* file, const char* value) { + FIRCLSFileWriteColletionEntryProlog(file); + + FIRCLSFileWriteHexEncodedString(file, value); + + FIRCLSFileWriteColletionEntryEpilog(file); +} + +NSArray* FIRCLSFileReadSections(const char* path, + bool deleteOnFailure, + NSObject* (^transformer)(id obj)) { + if (!FIRCLSIsValidPointer(path)) { + FIRCLSSDKLogError("Error: input path is invalid\n"); + return nil; + } + + NSString* pathString = [NSString stringWithUTF8String:path]; + NSString* contents = [NSString stringWithContentsOfFile:pathString + encoding:NSUTF8StringEncoding + error:nil]; + NSArray* components = [contents componentsSeparatedByString:@"\n"]; + + if (!components) { + if (deleteOnFailure) { + unlink(path); + } + + FIRCLSSDKLog("Unable to read file %s\n", path); + return nil; + } + + NSMutableArray* array = [NSMutableArray array]; + + // loop through all the entires, and + for (NSString* component in components) { + NSData* data = [component dataUsingEncoding:NSUTF8StringEncoding]; + + id obj = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; + if (!obj) { + continue; + } + + if (transformer) { + obj = transformer(obj); + } + + if (!obj) { + continue; + } + + [array addObject:obj]; + } + + return array; +} + +NSString* FIRCLSFileHexEncodeString(const char* string) { + size_t length = strlen(string); + char* encodedBuffer = malloc(length * 2 + 1); + + if (!encodedBuffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSFileHexEncodeString"); + return nil; + } + + memset(encodedBuffer, 0, length * 2 + 1); + + int bufferIndex = 0; + for (int i = 0; i < length; ++i) { + FIRCLSHexFromByte(string[i], &encodedBuffer[bufferIndex]); + + bufferIndex += 2; // 1 char => 2 hex values at a time + } + + NSString* stringObject = [NSString stringWithUTF8String:encodedBuffer]; + + free(encodedBuffer); + + return stringObject; +} + +NSString* FIRCLSFileHexDecodeString(const char* string) { + size_t length = strlen(string); + char* decodedBuffer = malloc(length); // too long, but safe + if (!decodedBuffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSFileHexDecodeString"); + return nil; + } + + memset(decodedBuffer, 0, length); + + for (int i = 0; i < length / 2; ++i) { + size_t index = i * 2; + + uint8_t hiNybble = FIRCLSNybbleFromChar(string[index]); + uint8_t lowNybble = FIRCLSNybbleFromChar(string[index + 1]); + + if (hiNybble == FIRCLSInvalidCharNybble || lowNybble == FIRCLSInvalidCharNybble) { + // char is invalid, abort loop + break; + } + + decodedBuffer[i] = (hiNybble << 4) | lowNybble; + } + + NSString* strObject = [NSString stringWithUTF8String:decodedBuffer]; + + free(decodedBuffer); + + return strObject; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.c new file mode 100644 index 00000000..93d50711 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.c @@ -0,0 +1,101 @@ +// Copyright 2019 Google +// +// 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. + +#include <dispatch/dispatch.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSContext.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +void FIRCLSSDKFileLog(FIRCLSInternalLogLevel level, const char* format, ...) { + if (!_firclsContext.readonly || !_firclsContext.writable) { + return; + } + + const char* path = _firclsContext.readonly->logPath; + if (!FIRCLSIsValidPointer(path)) { + return; + } + + if (_firclsContext.writable->internalLogging.logLevel > level) { + return; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + if (_firclsContext.writable->internalLogging.logFd == -1) { + _firclsContext.writable->internalLogging.logFd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644); + } + }); + + const int fd = _firclsContext.writable->internalLogging.logFd; + if (fd < 0) { + return; + } + + va_list args; + va_start(args, format); + +#if DEBUG && 0 + // It's nice to use printf here, so all the formatting works. However, its possible to hit a + // deadlock if you call vfprintf in a crash handler. So, this code is handy to keep, just in case, + // if there's a really tough thing to debug. + FILE* file = fopen(path, "a+"); + vfprintf(file, format, args); + fclose(file); +#else + size_t formatLength = strlen(format); + for (size_t idx = 0; idx < formatLength; ++idx) { + if (format[idx] != '%') { + write(fd, &format[idx], 1); + continue; + } + + idx++; // move to the format char + switch (format[idx]) { + case 'd': { + int value = va_arg(args, int); + FIRCLSFileFDWriteInt64(fd, value); + } break; + case 'u': { + uint32_t value = va_arg(args, uint32_t); + FIRCLSFileFDWriteUInt64(fd, value, false); + } break; + case 'p': { + uintptr_t value = va_arg(args, uintptr_t); + write(fd, "0x", 2); + FIRCLSFileFDWriteUInt64(fd, value, true); + } break; + case 's': { + const char* string = va_arg(args, const char*); + if (!string) { + string = "(null)"; + } + + write(fd, string, strlen(string)); + } break; + case 'x': { + unsigned int value = va_arg(args, unsigned int); + FIRCLSFileFDWriteUInt64(fd, value, true); + } break; + default: + // unhandled, back up to write out the percent + the format char + write(fd, &format[idx - 1], 2); + break; + } + } +#endif + va_end(args); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h new file mode 100644 index 00000000..3869889c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSInternalLogging.h @@ -0,0 +1,57 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdio.h> + +#if __OBJC__ +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#define FIRCLSDeveloperLog(label, __FORMAT__, ...) \ + FIRCLSDebugLog(@"[" label "] " __FORMAT__, ##__VA_ARGS__); +#endif + +typedef enum { + FIRCLSInternalLogLevelUnknown = 0, + FIRCLSInternalLogLevelDebug = 1, + FIRCLSInternalLogLevelInfo = 2, + FIRCLSInternalLogLevelWarn = 3, + FIRCLSInternalLogLevelError = 4 +} FIRCLSInternalLogLevel; + +typedef struct { + int logFd; + FIRCLSInternalLogLevel logLevel; +} FIRCLSInternalLoggingWritableContext; + +#define FIRCLSSDKLogDebug(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelDebug, "DEBUG [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#define FIRCLSSDKLogInfo(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelInfo, "INFO [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#define FIRCLSSDKLogWarn(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelWarn, "WARN [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) +#define FIRCLSSDKLogError(__FORMAT__, ...) \ + FIRCLSSDKFileLog(FIRCLSInternalLogLevelError, "ERROR [%s:%d] " __FORMAT__, __FUNCTION__, \ + __LINE__, ##__VA_ARGS__) + +#define FIRCLSSDKLog FIRCLSSDKLogWarn + +__BEGIN_DECLS + +void FIRCLSSDKFileLog(FIRCLSInternalLogLevel level, const char* format, ...) __printflike(2, 3); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h new file mode 100644 index 00000000..e03d99a9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h @@ -0,0 +1,24 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +__BEGIN_DECLS + +void FIRCLSDebugLog(NSString *message, ...); +void FIRCLSInfoLog(NSString *message, ...); +void FIRCLSWarningLog(NSString *message, ...); +void FIRCLSErrorLog(NSString *message, ...); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.m new file mode 100644 index 00000000..5600895d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSLogger.m @@ -0,0 +1,52 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" + +#import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h" + +FIRLoggerService kFIRLoggerCrashlytics = @"[Firebase/Crashlytics]"; + +NSString *const CrashlyticsMessageCode = @"I-CLS000000"; + +void FIRCLSDebugLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelDebug, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, + args_ptr); + va_end(args_ptr); +} + +void FIRCLSInfoLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelInfo, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, args_ptr); + va_end(args_ptr); +} + +void FIRCLSWarningLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelWarning, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, + args_ptr); + va_end(args_ptr); +} + +void FIRCLSErrorLog(NSString *message, ...) { + va_list args_ptr; + va_start(args_ptr, message); + FIRLogBasic(FIRLoggerLevelError, kFIRLoggerCrashlytics, CrashlyticsMessageCode, message, + args_ptr); + va_end(args_ptr); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.c new file mode 100644 index 00000000..2c705187 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.c @@ -0,0 +1,47 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h" + +#include <mach/mach_time.h> +#include <stdio.h> + +FIRCLSProfileMark FIRCLSProfilingStart(void) { + return mach_absolute_time(); +} + +double FIRCLSProfileEnd(FIRCLSProfileMark mark) { + uint64_t duration = mach_absolute_time() - mark; + + mach_timebase_info_data_t info; + mach_timebase_info(&info); + + if (info.denom == 0) { + return 0.0; + } + + // Convert to nanoseconds + duration *= info.numer; + duration /= info.denom; + + return (double)duration / (double)NSEC_PER_MSEC; // return time in milliseconds +} + +void FIRCLSProfileBlock(const char* label, void (^block)(void)) { + FIRCLSProfileMark mark = FIRCLSProfilingStart(); + + block(); + + fprintf(stderr, "[Profile] %s: %f ms\n", label, FIRCLSProfileEnd(mark)); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h new file mode 100644 index 00000000..5cc312f4 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSProfiling.h @@ -0,0 +1,29 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdint.h> + +typedef uint64_t FIRCLSProfileMark; + +__BEGIN_DECLS + +// high-resolution timing, returning the results in seconds +FIRCLSProfileMark FIRCLSProfilingStart(void); +double FIRCLSProfileEnd(FIRCLSProfileMark mark); + +void FIRCLSProfileBlock(const char* label, void (^block)(void)); + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.c new file mode 100644 index 00000000..c25e0c97 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.c @@ -0,0 +1,147 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#if defined(__arm__) || defined(__arm64__) +#include <mach/arm/thread_status.h> +#include <ptrauth.h> +#endif + +#if CLS_CPU_X86_64 +#define GET_IP_REGISTER(r) (r->__ss.__rip) +#define GET_FP_REGISTER(r) (r->__ss.__rbp) +#define GET_SP_REGISTER(r) (r->__ss.__rsp) +#define GET_LR_REGISTER(r) 0 +#define SET_IP_REGISTER(r, v) (r->__ss.__rip = v) +#define SET_FP_REGISTER(r, v) (r->__ss.__rbp = v) +#define SET_SP_REGISTER(r, v) (r->__ss.__rsp = v) +#define SET_LR_REGISTER(r, v) +#elif CLS_CPU_I386 +#define GET_IP_REGISTER(r) (r->__ss.__eip) +#define GET_FP_REGISTER(r) (r->__ss.__ebp) +#define GET_SP_REGISTER(r) (r->__ss.__esp) +#define GET_LR_REGISTER(r) 0 +#define SET_IP_REGISTER(r, v) (r->__ss.__eip = v) +#define SET_FP_REGISTER(r, v) (r->__ss.__ebp = v) +#define SET_SP_REGISTER(r, v) (r->__ss.__esp = v) +#define SET_LR_REGISTER(r, v) +#elif CLS_CPU_ARM64 +// The arm_thread_state64_get_* macros translate down to the AUTIA and AUTIB instructions which +// authenticate the address, but don't clear the upper bits. From the docs: +// "If the authentication passes, the upper bits of the address are restored to enable +// subsequent use of the address. the authentication fails, the upper bits are corrupted and +// any subsequent use of the address results in a Translation fault." +// Since we only want the address (with the metadata in the upper bits masked out), we used the +// ptrauth_strip macro to clear the upper bits. +// +// We found later that ptrauth_strip doesn't seem to do anything. In many cases, the upper bits were +// already stripped, so for most non-system-library code, Crashlytics would still symbolicate. But +// for system libraries, the upper bits were being left in even when we called ptrauth_strip. +// Instead, we're bit masking and only allowing the latter 36 bits. +#define CLS_PTRAUTH_STRIP(pointer) ((uintptr_t)pointer & 0x0000000FFFFFFFFF) +#define GET_IP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_pc(r->__ss))) +#define GET_FP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_fp(r->__ss))) +#define GET_SP_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_sp(r->__ss))) +#define GET_LR_REGISTER(r) (CLS_PTRAUTH_STRIP(arm_thread_state64_get_lr(r->__ss))) +#define SET_IP_REGISTER(r, v) arm_thread_state64_set_pc_fptr(r->__ss, (void*)v) +#define SET_FP_REGISTER(r, v) arm_thread_state64_set_fp(r->__ss, v) +#define SET_SP_REGISTER(r, v) arm_thread_state64_set_sp(r->__ss, v) +#define SET_LR_REGISTER(r, v) arm_thread_state64_set_lr_fptr(r->__ss, (void*)v) +#elif CLS_CPU_ARM +#define GET_IP_REGISTER(r) (r->__ss.__pc) +#define GET_FP_REGISTER(r) (r->__ss.__r[7]) +#define GET_SP_REGISTER(r) (r->__ss.__sp) +#define GET_LR_REGISTER(r) (r->__ss.__lr) +#define SET_IP_REGISTER(r, v) (r->__ss.__pc = v) +#define SET_FP_REGISTER(r, v) (r->__ss.__r[7] = v) +#define SET_SP_REGISTER(r, v) (r->__ss.__sp = v) +#define SET_LR_REGISTER(r, v) (r->__ss.__lr = v) +#else +#error "Architecture Unsupported" +#endif + +uintptr_t FIRCLSThreadContextGetPC(FIRCLSThreadContext* registers) { + if (!registers) { + return 0; + } + + return GET_IP_REGISTER(registers); +} + +uintptr_t FIRCLSThreadContextGetStackPointer(const FIRCLSThreadContext* registers) { + if (!registers) { + return 0; + } + + return GET_SP_REGISTER(registers); +} + +bool FIRCLSThreadContextSetStackPointer(FIRCLSThreadContext* registers, uintptr_t value) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + SET_SP_REGISTER(registers, value); + + return true; +} + +uintptr_t FIRCLSThreadContextGetLinkRegister(const FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(registers)) { + return 0; + } + + return GET_LR_REGISTER(registers); +} + +bool FIRCLSThreadContextSetLinkRegister(FIRCLSThreadContext* registers, uintptr_t value) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + SET_LR_REGISTER(registers, value); + + return true; +} + +bool FIRCLSThreadContextSetPC(FIRCLSThreadContext* registers, uintptr_t value) { + if (!registers) { + return false; + } + + SET_IP_REGISTER(registers, value); + + return true; +} + +uintptr_t FIRCLSThreadContextGetFramePointer(const FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(registers)) { + return 0; + } + + return GET_FP_REGISTER(registers); +} + +bool FIRCLSThreadContextSetFramePointer(FIRCLSThreadContext* registers, uintptr_t value) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + SET_FP_REGISTER(registers, value); + + return true; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h new file mode 100644 index 00000000..f281f665 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h @@ -0,0 +1,57 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdbool.h> +#include <sys/ucontext.h> + +#if CLS_CPU_ARM +#define FIRCLSThreadStateCount ARM_THREAD_STATE_COUNT +#define FIRCLSThreadState ARM_THREAD_STATE +#elif CLS_CPU_ARM64 +#define FIRCLSThreadStateCount ARM_THREAD_STATE64_COUNT +#define FIRCLSThreadState ARM_THREAD_STATE64 +#elif CLS_CPU_I386 +#define FIRCLSThreadStateCount x86_THREAD_STATE32_COUNT +#define FIRCLSThreadState x86_THREAD_STATE32 +#elif CLS_CPU_X86_64 +#define FIRCLSThreadStateCount x86_THREAD_STATE64_COUNT +#define FIRCLSThreadState x86_THREAD_STATE64 +#endif + +// _STRUCT_MCONTEXT was fixed to point to the right thing on ARM in the iOS 7.1 SDK +typedef _STRUCT_MCONTEXT FIRCLSThreadContext; + +// I'm not entirely sure what happened when, but this appears to have disappeared from +// the SDKs... +#if !defined(_STRUCT_UCONTEXT64) +typedef _STRUCT_UCONTEXT _STRUCT_UCONTEXT64; +#endif + +#pragma mark Register Access + +uintptr_t FIRCLSThreadContextGetPC(FIRCLSThreadContext* registers); +uintptr_t FIRCLSThreadContextGetStackPointer(const FIRCLSThreadContext* registers); +uintptr_t FIRCLSThreadContextGetFramePointer(const FIRCLSThreadContext* registers); + +bool FIRCLSThreadContextSetPC(FIRCLSThreadContext* registers, uintptr_t value); +bool FIRCLSThreadContextSetStackPointer(FIRCLSThreadContext* registers, uintptr_t value); +bool FIRCLSThreadContextSetFramePointer(FIRCLSThreadContext* registers, uintptr_t value); + +// The link register only exists on ARM platforms. +#if CLS_CPU_ARM || CLS_CPU_ARM64 +uintptr_t FIRCLSThreadContextGetLinkRegister(const FIRCLSThreadContext* registers); +bool FIRCLSThreadContextSetLinkRegister(FIRCLSThreadContext* registers, uintptr_t value); +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h new file mode 100644 index 00000000..84816a34 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h @@ -0,0 +1,54 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <mach/vm_types.h> +#include <stdbool.h> +#include <stdio.h> +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" + +#define FIRCLSIsValidPointer(x) ((uintptr_t)x >= 4096) +#define FIRCLSInvalidCharNybble (255) + +__BEGIN_DECLS + +void FIRCLSLookupFunctionPointer(void* ptr, void (^block)(const char* name, const char* lib)); + +void FIRCLSHexFromByte(uint8_t c, char output[]); +uint8_t FIRCLSNybbleFromChar(char c); + +bool FIRCLSReadMemory(vm_address_t src, void* dest, size_t len); +bool FIRCLSReadString(vm_address_t src, char** dest, size_t maxlen); + +const char* FIRCLSDupString(const char* string); + +bool FIRCLSUnlinkIfExists(const char* path); + +#if __OBJC__ +void FIRCLSDispatchAfter(float timeInSeconds, dispatch_queue_t queue, dispatch_block_t block); + +NSString* FIRCLSNormalizeUUID(NSString* value); +NSString* FIRCLSGenerateNormalizedUUID(void); + +NSString* FIRCLSNSDataToNSString(NSData* data); + +void FIRCLSAddOperationAfter(float timeInSeconds, NSOperationQueue* queue, void (^block)(void)); +#endif + +#if DEBUG +void FIRCLSPrintAUUID(const uint8_t* value); +#endif + +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.m new file mode 100644 index 00000000..48fe17a6 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Helpers/FIRCLSUtility.m @@ -0,0 +1,218 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <mach/mach.h> + +#include <dlfcn.h> + +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" + +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSUUID.h" + +#import <CommonCrypto/CommonHMAC.h> + +void FIRCLSLookupFunctionPointer(void* ptr, void (^block)(const char* name, const char* lib)) { + Dl_info info; + + if (dladdr(ptr, &info) == 0) { + block(NULL, NULL); + return; + } + + const char* name = "unknown"; + const char* lib = "unknown"; + + if (info.dli_sname) { + name = info.dli_sname; + } + + if (info.dli_fname) { + lib = info.dli_fname; + } + + block(name, lib); +} + +uint8_t FIRCLSNybbleFromChar(char c) { + if (c >= '0' && c <= '9') { + return c - '0'; + } + + if (c >= 'a' && c <= 'f') { + return c - 'a' + 10; + } + + if (c >= 'A' && c <= 'F') { + return c - 'A' + 10; + } + + return FIRCLSInvalidCharNybble; +} + +bool FIRCLSReadMemory(vm_address_t src, void* dest, size_t len) { + if (!FIRCLSIsValidPointer(src)) { + return false; + } + + vm_size_t readSize = len; + + return vm_read_overwrite(mach_task_self(), src, len, (pointer_t)dest, &readSize) == KERN_SUCCESS; +} + +bool FIRCLSReadString(vm_address_t src, char** dest, size_t maxlen) { + char c; + vm_address_t address; + + if (!dest) { + return false; + } + + // Walk the entire string. Not certain this is perfect... + for (address = src; address < src + maxlen; ++address) { + if (!FIRCLSReadMemory(address, &c, 1)) { + return false; + } + + if (c == 0) { + break; + } + } + + *dest = (char*)src; + + return true; +} + +const char* FIRCLSDupString(const char* string) { +#if CLS_MEMORY_PROTECTION_ENABLED + char* buffer; + size_t length; + + if (!string) { + return NULL; + } + + length = strlen(string); + buffer = FIRCLSAllocatorSafeAllocate(_firclsContext.allocator, length + 1, CLS_READONLY); + + memcpy(buffer, string, length); + + buffer[length] = 0; // null-terminate + + return buffer; +#else + return strdup(string); +#endif +} + +void FIRCLSDispatchAfter(float timeInSeconds, dispatch_queue_t queue, dispatch_block_t block) { + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeInSeconds * NSEC_PER_SEC)), queue, + block); +} + +bool FIRCLSUnlinkIfExists(const char* path) { + if (unlink(path) != 0) { + if (errno != ENOENT) { + return false; + } + } + + return true; +} + +/* +NSString* FIRCLSGenerateUUID(void) { + NSString* string; + + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + CFRelease(uuid); + + return string; +} +*/ + +NSString* FIRCLSNormalizeUUID(NSString* value) { + return [[value stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString]; +} + +NSString* FIRCLSGenerateNormalizedUUID(void) { + return FIRCLSNormalizeUUID(FIRCLSGenerateUUID()); +} + +NSString* FIRCLSNSDataToNSString(NSData* data) { + NSString* string; + char* buffer; + size_t size; + NSUInteger length; + + // we need 2 hex char for every byte of data, plus one more spot for a + // null terminator + length = [data length]; + size = (length * 2) + 1; + buffer = malloc(sizeof(char) * size); + + if (!buffer) { + FIRCLSErrorLog(@"Unable to malloc in FIRCLSNSDataToNSString"); + return nil; + } + + FIRCLSSafeHexToString([data bytes], length, buffer); + + string = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return string; +} + +/* +NSString* FIRCLSHashBytes(const void* bytes, size_t length) { + uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; + CC_SHA1(bytes, (CC_LONG)length, digest); + + NSData* result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + + return FIRCLSNSDataToNSString(result); +} + +NSString* FIRCLSHashNSData(NSData* data) { + return FIRCLSHashBytes([data bytes], [data length]); +} +*/ + +void FIRCLSAddOperationAfter(float timeInSeconds, NSOperationQueue* queue, void (^block)(void)) { + dispatch_queue_t afterQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + FIRCLSDispatchAfter(timeInSeconds, afterQueue, ^{ + [queue addOperationWithBlock:block]; + }); +} + +#if DEBUG +void FIRCLSPrintAUUID(const uint8_t* value) { + CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *(CFUUIDBytes*)value); + + NSString* string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + + CFRelease(uuid); + + FIRCLSDebugLog(@"%@", [[string stringByReplacingOccurrencesOfString:@"-" + withString:@""] lowercaseString]); +} +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h new file mode 100644 index 00000000..41a48967 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h @@ -0,0 +1,33 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is a model to identify a single execution of the app + */ +@interface FIRCLSExecutionIdentifierModel : NSObject + +/** + * Returns the launch identifier. This is a unique id that will remain constant until this process + * is relaunched. This value is useful for correlating events across kits and/or across reports at + * the process-lifecycle level. + */ +@property(nonatomic, readonly) NSString *executionID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.m new file mode 100644 index 00000000..163b3373 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.m @@ -0,0 +1,33 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Models/FIRCLSExecutionIdentifierModel.h" + +#import "Crashlytics/Shared/FIRCLSUUID.h" + +@implementation FIRCLSExecutionIdentifierModel + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _executionID = [[FIRCLSGenerateUUID() stringByReplacingOccurrencesOfString:@"-" + withString:@""] lowercaseString]; + + return self; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h new file mode 100644 index 00000000..dd988a95 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.h @@ -0,0 +1,73 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRCLSInternalReport; + +@interface FIRCLSFileManager : NSObject + +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, readonly) NSFileManager *underlyingFileManager; + +/** + * Returns the folder containing the settings file + */ +@property(nonatomic, readonly) NSString *settingsDirectoryPath; + +/** + * Returns the path to the settings file + */ +@property(nonatomic, readonly) NSString *settingsFilePath; + +/** + * Path to the file that holds the ttl and keys that invalidate settings + */ +@property(nonatomic, readonly) NSString *settingsCacheKeyPath; + +@property(nonatomic, readonly) NSString *rootPath; +@property(nonatomic, readonly) NSString *structurePath; +@property(nonatomic, readonly) NSString *activePath; +@property(nonatomic, readonly) NSString *processingPath; +@property(nonatomic, readonly) NSString *pendingPath; +@property(nonatomic, readonly) NSString *preparedPath; +@property(nonatomic, readonly) NSString *legacyPreparedPath; +@property(nonatomic, readonly) NSArray *activePathContents; +@property(nonatomic, readonly) NSArray *legacyPreparedPathContents; +@property(nonatomic, readonly) NSArray *preparedPathContents; +@property(nonatomic, readonly) NSArray *processingPathContents; + +- (BOOL)fileExistsAtPath:(NSString *)path; +- (BOOL)createFileAtPath:(NSString *)path + contents:(NSData *)data + attributes:(NSDictionary<NSFileAttributeKey, id> *)attr; +- (BOOL)createDirectoryAtPath:(NSString *)path; +- (BOOL)removeItemAtPath:(NSString *)path; +- (BOOL)removeContentsOfDirectoryAtPath:(NSString *)path; +- (BOOL)moveItemAtPath:(NSString *)path toDirectory:(NSString *)destDir; +- (void)enumerateFilesInDirectory:(NSString *)directory + usingBlock:(void (^)(NSString *filePath, NSString *extension))block; +- (NSNumber *)fileSizeAtPath:(NSString *)path; +- (NSArray *)contentsOfDirectory:(NSString *)path; + +// logic of managing files/directories +- (BOOL)createReportDirectories; +- (NSString *)setupNewPathForExecutionIdentifier:(NSString *)identifier; + +- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error; + +- (NSData *)dataWithContentsOfFile:(NSString *)path; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.m new file mode 100644 index 00000000..b78e0f29 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSFileManager.m @@ -0,0 +1,279 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" + +NSString *const FIRCLSCacheDirectoryName = @"com.crashlytics.data"; +NSString *const FIRCLSCacheVersion = @"v5"; + +@interface FIRCLSFileManager () { + NSString *_rootPath; +} + +@end + +@implementation FIRCLSFileManager + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _underlyingFileManager = [NSFileManager defaultManager]; + + NSString *path = + [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; + path = [path stringByAppendingPathComponent:FIRCLSCacheDirectoryName]; + path = [path stringByAppendingPathComponent:[self pathNamespace]]; + _rootPath = [path copy]; + + return self; +} + +#pragma mark - Core API + +- (BOOL)fileExistsAtPath:(NSString *)path { + return [_underlyingFileManager fileExistsAtPath:path]; +} + +- (BOOL)createFileAtPath:(NSString *)path + contents:(nullable NSData *)data + attributes:(nullable NSDictionary<NSFileAttributeKey, id> *)attr { + return [_underlyingFileManager createFileAtPath:path contents:data attributes:attr]; +} + +- (BOOL)createDirectoryAtPath:(NSString *)path { + NSDictionary *attributes; + NSError *error; + + attributes = @{NSFilePosixPermissions : [NSNumber numberWithShort:0755]}; + error = nil; + + if (![[self underlyingFileManager] createDirectoryAtPath:path + withIntermediateDirectories:YES + attributes:attributes + error:&error]) { + FIRCLSErrorLog(@"Unable to create directory %@", error); + return NO; + } + + return YES; +} + +- (BOOL)removeItemAtPath:(NSString *)path { + NSError *error; + + error = nil; + if (![[self underlyingFileManager] removeItemAtPath:path error:&error] || !path) { + FIRCLSErrorLog(@"Failed to remove file %@: %@", path, error); + + return NO; + } + + return YES; +} + +- (BOOL)removeContentsOfDirectoryAtPath:(NSString *)path { + __block BOOL success = YES; + + // only return true if we were able to remove every item in the directory (or it was empty) + + [self enumerateFilesInDirectory:path + usingBlock:^(NSString *filePath, NSString *extension) { + success = [self removeItemAtPath:filePath] && success; + }]; + + return success; +} + +- (BOOL)moveItemAtPath:(NSString *)path toDirectory:(NSString *)destDir { + NSString *destPath; + NSError *error; + + destPath = [destDir stringByAppendingPathComponent:[path lastPathComponent]]; + error = nil; + + if (!path || !destPath) { + FIRCLSErrorLog(@"Failed to move file, inputs invalid"); + + return NO; + } + + if (![[self underlyingFileManager] moveItemAtPath:path toPath:destPath error:&error]) { + FIRCLSErrorLog(@"Failed to move file: %@", error); + + return NO; + } + + return YES; +} + +- (void)enumerateFilesInDirectory:(NSString *)directory + usingBlock:(void (^)(NSString *filePath, NSString *extension))block { + for (NSString *path in [[self underlyingFileManager] contentsOfDirectoryAtPath:directory + error:nil]) { + NSString *extension; + NSString *fullPath; + + // Skip files that start with a dot. This is important, because if you try to move a .DS_Store + // file, it will fail if the target directory also has a .DS_Store file in it. Plus, its + // wasteful, because we don't care about dot files. + if ([path hasPrefix:@"."]) { + continue; + } + + extension = [path pathExtension]; + fullPath = [directory stringByAppendingPathComponent:path]; + if (block) { + block(fullPath, extension); + } + } +} + +- (NSNumber *)fileSizeAtPath:(NSString *)path { + NSError *error = nil; + NSDictionary *attrs = [[self underlyingFileManager] attributesOfItemAtPath:path error:&error]; + + if (!attrs) { + FIRCLSErrorLog(@"Unable to read file size: %@", error); + return nil; + } + + return [attrs objectForKey:NSFileSize]; +} + +- (NSArray *)contentsOfDirectory:(NSString *)path { + NSMutableArray *array = [NSMutableArray array]; + + [self enumerateFilesInDirectory:path + usingBlock:^(NSString *filePath, NSString *extension) { + [array addObject:filePath]; + }]; + + return [array copy]; +} + +#pragma - Properties +- (NSString *)pathNamespace { + return FIRCLSApplicationGetBundleIdentifier(); +} + +- (NSString *)versionedPath { + return [[self rootPath] stringByAppendingPathComponent:FIRCLSCacheVersion]; +} + +#pragma - Settings Paths + +// This path should be different than the structurePath because the +// settings download operations will delete the settings directory, +// which would delete crash reports if these were the same +- (NSString *)settingsDirectoryPath { + return [[self versionedPath] stringByAppendingPathComponent:@"settings"]; +} + +- (NSString *)settingsFilePath { + return [[self settingsDirectoryPath] stringByAppendingPathComponent:@"settings.json"]; +} + +- (NSString *)settingsCacheKeyPath { + return [[self settingsDirectoryPath] stringByAppendingPathComponent:@"cache-key.json"]; +} + +#pragma - Report Paths +- (NSString *)structurePath { + return [[self versionedPath] stringByAppendingPathComponent:@"reports"]; +} + +- (NSString *)activePath { + return [[self structurePath] stringByAppendingPathComponent:@"active"]; +} + +- (NSString *)pendingPath { + return [[self structurePath] stringByAppendingPathComponent:@"pending"]; +} + +- (NSString *)processingPath { + return [[self structurePath] stringByAppendingPathComponent:@"processing"]; +} + +- (NSString *)legacyPreparedPath { + return [[self structurePath] stringByAppendingPathComponent:@"prepared-legacy"]; +} + +- (NSString *)preparedPath { + return [[self structurePath] stringByAppendingPathComponent:@"prepared"]; +} + +- (NSArray *)activePathContents { + return [self contentsOfDirectory:[self activePath]]; +} + +- (NSArray *)legacyPreparedPathContents { + return [self contentsOfDirectory:[self legacyPreparedPath]]; +} + +- (NSArray *)preparedPathContents { + return [self contentsOfDirectory:[self preparedPath]]; +} + +- (NSArray *)processingPathContents { + return [self contentsOfDirectory:[self processingPath]]; +} + +#pragma mark - Logic +- (BOOL)createReportDirectories { + if (![self createDirectoryAtPath:[self activePath]]) { + return NO; + } + + if (![self createDirectoryAtPath:[self processingPath]]) { + return NO; + } + + if (![self createDirectoryAtPath:[self legacyPreparedPath]]) { + return NO; + } + + if (![self createDirectoryAtPath:[self preparedPath]]) { + return NO; + } + + return YES; +} + +- (NSString *)setupNewPathForExecutionIdentifier:(NSString *)identifier { + NSString *path = [[self activePath] stringByAppendingPathComponent:identifier]; + + if (![self createDirectoryAtPath:path]) { + return nil; + } + + return path; +} + +- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error { + return [self.underlyingFileManager moveItemAtPath:srcPath toPath:dstPath error:error]; +} + +// Wrapper over NSData so the method can be mocked for unit tests +- (NSData *)dataWithContentsOfFile:(NSString *)path { + return [NSData dataWithContentsOfFile:path]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h new file mode 100644 index 00000000..6100c8a9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h @@ -0,0 +1,46 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRInstallations; + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is a model for identifying an installation of an app + */ +@interface FIRCLSInstallIdentifierModel : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +- (instancetype)initWithInstallations:(FIRInstallations *)instanceID NS_DESIGNATED_INITIALIZER; + +/** + * Returns the backwards compatible Crashlytics Installation UUID + */ +@property(nonatomic, readonly) NSString *installID; + +/** + * To support end-users rotating Install IDs, this will check and rotate the Install ID, + * which is a costly operation performance-wise. To keep the startup time impact down, call this in + * a background thread. + * + * The block will be called on a background thread. + */ +- (void)regenerateInstallIDIfNeededWithBlock:(void (^)(BOOL didRotate))callback; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m new file mode 100644 index 00000000..dcfde984 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.m @@ -0,0 +1,161 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h" + +#import "FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h" + +#import "Crashlytics/Crashlytics/FIRCLSUserDefaults/FIRCLSUserDefaults.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSUUID.h" + +static NSString *const FIRCLSInstallationUUIDKey = @"com.crashlytics.iuuid"; +static NSString *const FIRCLSInstallationIIDHashKey = @"com.crashlytics.install.iid"; + +// Legacy key that is automatically removed +static NSString *const FIRCLSInstallationADIDKey = @"com.crashlytics.install.adid"; + +@interface FIRCLSInstallIdentifierModel () + +@property(nonatomic, copy) NSString *installID; + +@property(nonatomic, readonly) FIRInstallations *installations; + +@end + +@implementation FIRCLSInstallIdentifierModel + +// This needs to be synthesized so we can set without using the setter in the constructor and +// overridden setters and getters +@synthesize installID = _installID; + +- (instancetype)initWithInstallations:(FIRInstallations *)installations { + self = [super init]; + if (!self) { + return nil; + } + + // capture the install ID information + _installID = [self readInstallationUUID].copy; + _installations = installations; + + if (!_installID) { + FIRCLSDebugLog(@"Generating Install ID"); + _installID = [self generateInstallationUUID].copy; + + FIRCLSUserDefaults *defaults = [FIRCLSUserDefaults standardUserDefaults]; + [defaults synchronize]; + } + + return self; +} + +- (NSString *)installID { + @synchronized(self) { + return _installID; + } +} + +- (void)setInstallID:(NSString *)installID { + @synchronized(self) { + _installID = installID; + } +} + +/** + * Reads installation UUID stored in persistent storage. + * If the installation UUID is stored in legacy key, migrates it over to the new key. + */ +- (NSString *)readInstallationUUID { + return [[FIRCLSUserDefaults standardUserDefaults] objectForKey:FIRCLSInstallationUUIDKey]; +} + +/** + * Generates a new UUID and saves it in persistent storage. + * Does not sychronize the user defaults (to allow optimized + * batching of user default synchronizing) + */ +- (NSString *)generateInstallationUUID { + NSString *UUID = FIRCLSGenerateUUID(); + FIRCLSUserDefaults *userDefaults = [FIRCLSUserDefaults standardUserDefaults]; + [userDefaults setObject:UUID forKey:FIRCLSInstallationUUIDKey]; + return UUID; +} + +#pragma mark Privacy Shield + +/** + * To support privacy shield we need to regenerate the install id when the IID changes. + * + * This is a blocking, slow call that must be called on a background thread. + */ +- (void)regenerateInstallIDIfNeededWithBlock:(void (^)(BOOL didRotate))callback { + // This callback is on the main thread + [self.installations + installationIDWithCompletion:^(NSString *_Nullable currentIID, NSError *_Nullable error) { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + BOOL didRotate = [self rotateCrashlyticsInstallUUIDWithIID:currentIID error:error]; + callback(didRotate); + }); + }]; +} + +- (BOOL)rotateCrashlyticsInstallUUIDWithIID:(NSString *_Nullable)currentIID + error:(NSError *_Nullable)error { + BOOL didRotate = NO; + + FIRCLSUserDefaults *defaults = [FIRCLSUserDefaults standardUserDefaults]; + + // Remove the legacy ID + NSString *adID = [defaults objectForKey:FIRCLSInstallationADIDKey]; + if (adID.length != 0) { + [defaults removeObjectForKey:FIRCLSInstallationADIDKey]; + [defaults synchronize]; + } + + if (error != nil) { + FIRCLSErrorLog(@"Failed to get Firebase Instance ID: %@", error); + return didRotate; + } + + if (currentIID.length == 0) { + FIRCLSErrorLog(@"Firebase Instance ID was empty when checked for changes"); + return didRotate; + } + + NSString *currentIIDHash = + FIRCLS256HashNSData([currentIID dataUsingEncoding:NSUTF8StringEncoding]); + NSString *lastIIDHash = [defaults objectForKey:FIRCLSInstallationIIDHashKey]; + + // If the IDs are the same, we never regenerate + if ([lastIIDHash isEqualToString:currentIIDHash]) { + return didRotate; + } + + // If we had an FIID saved, we know it's not an upgrade scenario, so we can regenerate + if (lastIIDHash.length != 0) { + FIRCLSDebugLog(@"Regenerating Install ID"); + self.installID = [self generateInstallationUUID].copy; + didRotate = YES; + } + + // Write the new FIID to UserDefaults + [defaults setObject:currentIIDHash forKey:FIRCLSInstallationIIDHashKey]; + [defaults synchronize]; + + return didRotate; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h new file mode 100644 index 00000000..b303ebe0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h @@ -0,0 +1,117 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" + +extern NSString *const FIRCLSReportBinaryImageFile; +extern NSString *const FIRCLSReportExceptionFile; +extern NSString *const FIRCLSReportCustomExceptionAFile; +extern NSString *const FIRCLSReportCustomExceptionBFile; +extern NSString *const FIRCLSReportSignalFile; +#if CLS_MACH_EXCEPTION_SUPPORTED +extern NSString *const FIRCLSReportMachExceptionFile; +#endif +extern NSString *const FIRCLSReportErrorAFile; +extern NSString *const FIRCLSReportErrorBFile; +extern NSString *const FIRCLSReportLogAFile; +extern NSString *const FIRCLSReportLogBFile; +extern NSString *const FIRCLSReportMetadataFile; +extern NSString *const FIRCLSReportInternalIncrementalKVFile; +extern NSString *const FIRCLSReportInternalCompactedKVFile; +extern NSString *const FIRCLSReportUserIncrementalKVFile; +extern NSString *const FIRCLSReportUserCompactedKVFile; + +@class FIRCLSFileManager; + +@interface FIRCLSInternalReport : NSObject + ++ (instancetype)reportWithPath:(NSString *)path; +- (instancetype)initWithPath:(NSString *)path + executionIdentifier:(NSString *)identifier NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithPath:(NSString *)path; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + ++ (NSArray *)crashFileNames; + +@property(nonatomic, copy, readonly) NSString *directoryName; +@property(nonatomic, copy) NSString *path; +@property(nonatomic, assign, readonly) BOOL needsToBeSubmitted; + +// content paths +@property(nonatomic, copy, readonly) NSString *binaryImagePath; +@property(nonatomic, copy, readonly) NSString *metadataPath; + +- (void)enumerateSymbolicatableFilesInContent:(void (^)(NSString *path))block; + +- (NSString *)pathForContentFile:(NSString *)name; + +// Metadata Helpers + +/** + * Returns the org id for the report. + **/ +@property(nonatomic, copy, readonly) NSString *orgID; + +/** + * Returns the Install UUID for the report. + **/ +@property(nonatomic, copy, readonly) NSString *installID; + +/** + * Returns YES if report contains a signal, mach exception or unhandled exception record, NO + * otherwise. + **/ +@property(nonatomic, assign, readonly) BOOL isCrash; + +/** + * Returns the session identifier for the report. + **/ +@property(nonatomic, copy, readonly) NSString *identifier; + +/** + * Returns the custom key value data for the report. + **/ +@property(nonatomic, copy, readonly) NSDictionary *customKeys; + +/** + * Returns the CFBundleVersion of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleVersion; + +/** + * Returns the CFBundleShortVersionString of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleShortVersionString; + +/** + * Returns the date that the report was created. + **/ +@property(nonatomic, copy, readonly) NSDate *dateCreated; + +@property(nonatomic, copy, readonly) NSDate *crashedOnDate; + +/** + * Returns the os version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSVersion; + +/** + * Returns the os build version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSBuildVersion; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m new file mode 100644 index 00000000..c4ca2d75 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSInternalReport.m @@ -0,0 +1,253 @@ +// Copyright 2019 Google +// +// 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. + +// TODO: Remove this class after the uploading of reports via GoogleDataTransport is no longer an +// experiment + +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" + +NSString *const FIRCLSReportBinaryImageFile = @"binary_images.clsrecord"; +NSString *const FIRCLSReportExceptionFile = @"exception.clsrecord"; +NSString *const FIRCLSReportCustomExceptionAFile = @"custom_exception_a.clsrecord"; +NSString *const FIRCLSReportCustomExceptionBFile = @"custom_exception_b.clsrecord"; +NSString *const FIRCLSReportSignalFile = @"signal.clsrecord"; +#if CLS_MACH_EXCEPTION_SUPPORTED +NSString *const FIRCLSReportMachExceptionFile = @"mach_exception.clsrecord"; +#endif +NSString *const FIRCLSReportMetadataFile = @"metadata.clsrecord"; +NSString *const FIRCLSReportErrorAFile = @"errors_a.clsrecord"; +NSString *const FIRCLSReportErrorBFile = @"errors_b.clsrecord"; +NSString *const FIRCLSReportLogAFile = @"log_a.clsrecord"; +NSString *const FIRCLSReportLogBFile = @"log_b.clsrecord"; +NSString *const FIRCLSReportInternalIncrementalKVFile = @"internal_incremental_kv.clsrecord"; +NSString *const FIRCLSReportInternalCompactedKVFile = @"internal_compacted_kv.clsrecord"; +NSString *const FIRCLSReportUserIncrementalKVFile = @"user_incremental_kv.clsrecord"; +NSString *const FIRCLSReportUserCompactedKVFile = @"user_compacted_kv.clsrecord"; + +@interface FIRCLSInternalReport () { + NSString *_identifier; + NSString *_path; + NSArray *_metadataSections; +} + +@end + +@implementation FIRCLSInternalReport + ++ (instancetype)reportWithPath:(NSString *)path { + return [[self alloc] initWithPath:path]; +} + +#pragma mark - Initialization +/** + * Initializes a new report, i.e. one without metadata on the file system yet. + */ +- (instancetype)initWithPath:(NSString *)path executionIdentifier:(NSString *)identifier { + self = [super init]; + if (!self) { + return self; + } + + if (!path || !identifier) { + return nil; + } + + [self setPath:path]; + + _identifier = [identifier copy]; + + return self; +} + +/** + * Initializes a pre-existing report, i.e. one with metadata on the file system. + */ +- (instancetype)initWithPath:(NSString *)path { + NSString *metadataPath = [path stringByAppendingPathComponent:FIRCLSReportMetadataFile]; + NSString *identifier = [[[[self.class readFIRCLSFileAtPath:metadataPath] objectAtIndex:0] + objectForKey:@"identity"] objectForKey:@"session_id"]; + if (!identifier) { + FIRCLSErrorLog(@"Unable to read identifier at path %@", path); + } + return [self initWithPath:path executionIdentifier:identifier]; +} + +#pragma mark - Path Helpers +- (NSString *)directoryName { + return self.path.lastPathComponent; +} + +- (NSString *)pathForContentFile:(NSString *)name { + return [[self path] stringByAppendingPathComponent:name]; +} + +- (NSString *)metadataPath { + return [[self path] stringByAppendingPathComponent:FIRCLSReportMetadataFile]; +} + +- (NSString *)binaryImagePath { + return [self pathForContentFile:FIRCLSReportBinaryImageFile]; +} + +#pragma mark - Processing Methods +- (BOOL)needsToBeSubmitted { + NSArray *reportFiles = @[ + FIRCLSReportExceptionFile, FIRCLSReportSignalFile, FIRCLSReportCustomExceptionAFile, + FIRCLSReportCustomExceptionBFile, +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSReportMachExceptionFile, +#endif + FIRCLSReportErrorAFile, FIRCLSReportErrorBFile + ]; + return [self checkExistenceOfAtLeastOnceFileInArray:reportFiles]; +} + +// These are purposefully in order of precedence. If duplicate data exists +// in any crash file, the exception file's contents take precedence over the +// rest, for example +// +// Do not change the order of this. +// ++ (NSArray *)crashFileNames { + static NSArray *files; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + files = @[ + FIRCLSReportExceptionFile, +#if CLS_MACH_EXCEPTION_SUPPORTED + FIRCLSReportMachExceptionFile, +#endif + FIRCLSReportSignalFile + ]; + }); + return files; +} + +- (BOOL)isCrash { + NSArray *crashFiles = [FIRCLSInternalReport crashFileNames]; + return [self checkExistenceOfAtLeastOnceFileInArray:crashFiles]; +} + +- (BOOL)checkExistenceOfAtLeastOnceFileInArray:(NSArray *)files { + NSFileManager *manager = [NSFileManager defaultManager]; + + for (NSString *fileName in files) { + NSString *path = [self pathForContentFile:fileName]; + + if ([manager fileExistsAtPath:path]) { + return YES; + } + } + + return NO; +} + +- (void)enumerateSymbolicatableFilesInContent:(void (^)(NSString *path))block { + for (NSString *fileName in [FIRCLSInternalReport crashFileNames]) { + NSString *path = [self pathForContentFile:fileName]; + + block(path); + } +} + +#pragma mark - Metadata helpers ++ (NSArray *)readFIRCLSFileAtPath:(NSString *)path { + NSArray *sections = FIRCLSFileReadSections([path fileSystemRepresentation], false, nil); + + if ([sections count] == 0) { + return nil; + } + + return sections; +} + +- (NSArray *)metadataSections { + if (!_metadataSections) { + _metadataSections = [self.class readFIRCLSFileAtPath:self.metadataPath]; + } + return _metadataSections; +} + +- (NSString *)orgID { + return + [[[self.metadataSections objectAtIndex:0] objectForKey:@"identity"] objectForKey:@"org_id"]; +} + +- (NSDictionary *)customKeys { + return nil; +} + +- (NSString *)bundleVersion { + return [[[self.metadataSections objectAtIndex:2] objectForKey:@"application"] + objectForKey:@"build_version"]; +} + +- (NSString *)bundleShortVersionString { + return [[[self.metadataSections objectAtIndex:2] objectForKey:@"application"] + objectForKey:@"display_version"]; +} + +- (NSDate *)dateCreated { + NSUInteger unixtime = [[[[self.metadataSections objectAtIndex:0] objectForKey:@"identity"] + objectForKey:@"started_at"] unsignedIntegerValue]; + + return [NSDate dateWithTimeIntervalSince1970:unixtime]; +} + +- (NSDate *)crashedOnDate { + if (!self.isCrash) { + return nil; + } + +#if CLS_MACH_EXCEPTION_SUPPORTED + // try the mach exception first, because it is more common + NSDate *date = [self timeFromCrashContentFile:FIRCLSReportMachExceptionFile + sectionName:@"mach_exception"]; + if (date) { + return date; + } +#endif + + return [self timeFromCrashContentFile:FIRCLSReportSignalFile sectionName:@"signal"]; +} + +- (NSDate *)timeFromCrashContentFile:(NSString *)fileName sectionName:(NSString *)sectionName { + // This works because both signal and mach exception files have the same structure to extract + // the "time" component + NSString *path = [self pathForContentFile:fileName]; + + NSNumber *timeValue = [[[[self.class readFIRCLSFileAtPath:path] objectAtIndex:0] + objectForKey:sectionName] objectForKey:@"time"]; + if (timeValue == nil) { + return nil; + } + + return [NSDate dateWithTimeIntervalSince1970:[timeValue unsignedIntegerValue]]; +} + +- (NSString *)OSVersion { + return [[[self.metadataSections objectAtIndex:1] objectForKey:@"host"] + objectForKey:@"os_display_version"]; +} + +- (NSString *)OSBuildVersion { + return [[[self.metadataSections objectAtIndex:1] objectForKey:@"host"] + objectForKey:@"os_build_version"]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h new file mode 100644 index 00000000..464dff73 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.h @@ -0,0 +1,110 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * The CLSCrashReport protocol is deprecated. See the CLSReport class and the CrashyticsDelegate + * changes for details. + **/ +@protocol FIRCLSCrashReport <NSObject> + +@property(nonatomic, copy, readonly) NSString *identifier; +@property(nonatomic, copy, readonly) NSDictionary *customKeys; +@property(nonatomic, copy, readonly) NSString *bundleVersion; +@property(nonatomic, copy, readonly) NSString *bundleShortVersionString; +@property(nonatomic, readonly, nullable) NSDate *crashedOnDate; +@property(nonatomic, copy, readonly) NSString *OSVersion; +@property(nonatomic, copy, readonly) NSString *OSBuildVersion; + +@end + +/** + * The CLSReport exposes an interface to the phsyical report that Crashlytics has created. You can + * use this class to get information about the event, and can also set some values after the + * event has occurred. + **/ +@interface FIRCLSReport : NSObject <FIRCLSCrashReport> + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Returns the session identifier for the report. + **/ +@property(nonatomic, copy, readonly) NSString *identifier; + +/** + * Returns the custom key value data for the report. + **/ +@property(nonatomic, copy, readonly) NSDictionary *customKeys; + +/** + * Returns the CFBundleVersion of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleVersion; + +/** + * Returns the CFBundleShortVersionString of the application that generated the report. + **/ +@property(nonatomic, copy, readonly) NSString *bundleShortVersionString; + +/** + * Returns the date that the report was created. + **/ +@property(nonatomic, copy, readonly) NSDate *dateCreated; + +/** + * Returns the os version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSVersion; + +/** + * Returns the os build version that the application crashed on. + **/ +@property(nonatomic, copy, readonly) NSString *OSBuildVersion; + +/** + * Returns YES if the report contains any crash information, otherwise returns NO. + **/ +@property(nonatomic, assign, readonly) BOOL isCrash; + +/** + * You can use this method to set, after the event, additional custom keys. The rules + * and semantics for this method are the same as those documented in FIRCrashlytics.h. Be aware + * that the maximum size and count of custom keys is still enforced, and you can overwrite keys + * and/or cause excess keys to be deleted by using this method. + **/ +- (void)setObjectValue:(nullable id)value forKey:(NSString *)key; + +/** + * Record an application-specific user identifier. See FIRCrashlytics.h for details. + **/ +@property(nonatomic, copy, nullable) NSString *userIdentifier; + +/** + * Record a user name. See FIRCrashlytics.h for details. + **/ +@property(nonatomic, copy, nullable) NSString *userName; + +/** + * Record a user email. See FIRCrashlytics.h for details. + **/ +@property(nonatomic, copy, nullable) NSString *userEmail; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.m new file mode 100644 index 00000000..a518e727 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport.m @@ -0,0 +1,241 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Components/FIRCLSContext.h" +#import "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#import "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h" + +@interface FIRCLSReport () { + FIRCLSInternalReport *_internalReport; + uint32_t _internalKVCounter; + uint32_t _userKVCounter; + + NSString *_internalCompactedKVFile; + NSString *_internalIncrementalKVFile; + NSString *_userCompactedKVFile; + NSString *_userIncrementalKVFile; + + BOOL _readOnly; + + // cached values, to ensure that their contents remain valid + // even if the report is deleted + NSString *_identifer; + NSString *_bundleVersion; + NSString *_bundleShortVersionString; + NSDate *_dateCreated; + NSDate *_crashedOnDate; + NSString *_OSVersion; + NSString *_OSBuildVersion; + NSNumber *_isCrash; + NSDictionary *_customKeys; +} + +@end + +@implementation FIRCLSReport + +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report + prefetchData:(BOOL)shouldPrefetch { + self = [super init]; + if (!self) { + return nil; + } + + _internalReport = report; + + // TODO: correct kv accounting + // The internal report will have non-zero compacted and incremental keys. The right thing to do + // is count them, so we can kick off compactions/pruning at the right times. By + // setting this value to zero, we're allowing more entries to be made than there really + // should be. Not the end of the world, but we should do better eventually. + _internalKVCounter = 0; + _userKVCounter = 0; + + _internalCompactedKVFile = + [self.internalReport pathForContentFile:FIRCLSReportInternalCompactedKVFile]; + _internalIncrementalKVFile = + [self.internalReport pathForContentFile:FIRCLSReportInternalIncrementalKVFile]; + _userCompactedKVFile = [self.internalReport pathForContentFile:FIRCLSReportUserCompactedKVFile]; + _userIncrementalKVFile = + [self.internalReport pathForContentFile:FIRCLSReportUserIncrementalKVFile]; + + _readOnly = shouldPrefetch; + + if (shouldPrefetch) { + _identifer = report.identifier; + _bundleVersion = report.bundleVersion; + _bundleShortVersionString = report.bundleShortVersionString; + _dateCreated = report.dateCreated; + _crashedOnDate = report.crashedOnDate; + _OSVersion = report.OSVersion; + _OSBuildVersion = report.OSBuildVersion; + _isCrash = [NSNumber numberWithBool:report.isCrash]; + + _customKeys = [self readCustomKeys]; + } + + return self; +} + +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report { + return [self initWithInternalReport:report prefetchData:NO]; +} + +#pragma mark - Helpers +- (FIRCLSUserLoggingKVStorage)internalKVStorage { + FIRCLSUserLoggingKVStorage storage; + + storage.maxCount = _firclsContext.readonly->logging.internalKVStorage.maxCount; + storage.maxIncrementalCount = + _firclsContext.readonly->logging.internalKVStorage.maxIncrementalCount; + storage.compactedPath = [_internalCompactedKVFile fileSystemRepresentation]; + storage.incrementalPath = [_internalIncrementalKVFile fileSystemRepresentation]; + + return storage; +} + +- (FIRCLSUserLoggingKVStorage)userKVStorage { + FIRCLSUserLoggingKVStorage storage; + + storage.maxCount = _firclsContext.readonly->logging.userKVStorage.maxCount; + storage.maxIncrementalCount = _firclsContext.readonly->logging.userKVStorage.maxIncrementalCount; + storage.compactedPath = [_userCompactedKVFile fileSystemRepresentation]; + storage.incrementalPath = [_userIncrementalKVFile fileSystemRepresentation]; + + return storage; +} + +- (BOOL)canRecordNewValues { + return !_readOnly && FIRCLSContextIsInitialized(); +} + +- (void)recordValue:(id)value forInternalKey:(NSString *)key { + if (!self.canRecordNewValues) { + return; + } + + FIRCLSUserLoggingKVStorage storage = [self internalKVStorage]; + + FIRCLSUserLoggingRecordKeyValue(key, value, &storage, &_internalKVCounter); +} + +- (void)recordValue:(id)value forUserKey:(NSString *)key { + if (!self.canRecordNewValues) { + return; + } + + FIRCLSUserLoggingKVStorage storage = [self userKVStorage]; + + FIRCLSUserLoggingRecordKeyValue(key, value, &storage, &_userKVCounter); +} + +- (NSDictionary *)readCustomKeys { + FIRCLSUserLoggingKVStorage storage = [self userKVStorage]; + + // return decoded entries + return FIRCLSUserLoggingGetCompactedKVEntries(&storage, true); +} + +#pragma mark - Metadata helpers + +- (NSString *)identifier { + if (!_identifer) { + _identifer = self.internalReport.identifier; + } + + return _identifer; +} + +- (NSDictionary *)customKeys { + if (!_customKeys) { + _customKeys = [self readCustomKeys]; + } + + return _customKeys; +} + +- (NSString *)bundleVersion { + if (!_bundleVersion) { + _bundleVersion = self.internalReport.bundleVersion; + } + + return _bundleVersion; +} + +- (NSString *)bundleShortVersionString { + if (!_bundleShortVersionString) { + _bundleShortVersionString = self.internalReport.bundleShortVersionString; + } + + return _bundleShortVersionString; +} + +- (NSDate *)dateCreated { + if (!_dateCreated) { + _dateCreated = self.internalReport.dateCreated; + } + + return _dateCreated; +} + +// for compatibility with the CLSCrashReport Protocol +- (NSDate *)crashedOnDate { + if (!_crashedOnDate) { + _crashedOnDate = self.internalReport.crashedOnDate; + } + + return _crashedOnDate; +} + +- (NSString *)OSVersion { + if (!_OSVersion) { + _OSVersion = self.internalReport.OSVersion; + } + + return _OSVersion; +} + +- (NSString *)OSBuildVersion { + if (!_OSBuildVersion) { + _OSBuildVersion = self.internalReport.OSBuildVersion; + } + + return _OSBuildVersion; +} + +- (BOOL)isCrash { + if (_isCrash == nil) { + _isCrash = [NSNumber numberWithBool:self.internalReport.isCrash]; + } + + return [_isCrash boolValue]; +} + +#pragma mark - Public Read/Write Methods +- (void)setObjectValue:(id)value forKey:(NSString *)key { + [self recordValue:value forUserKey:key]; +} + +- (NSString *)userIdentifier { + return nil; +} + +- (void)setUserIdentifier:(NSString *)userIdentifier { + [self recordValue:userIdentifier forInternalKey:FIRCLSUserIdentifierKey]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h new file mode 100644 index 00000000..93b2bcc8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSReport_Private.h @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Models/FIRCLSReport.h" + +@class FIRCLSInternalReport; + +@interface FIRCLSReport () + +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report + prefetchData:(BOOL)shouldPrefetch NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithInternalReport:(FIRCLSInternalReport *)report; + +@property(nonatomic, strong, readonly) FIRCLSInternalReport *internalReport; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h new file mode 100644 index 00000000..f45b45fd --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.h @@ -0,0 +1,134 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +@class FIRCLSApplicationIdentifierModel; +@class FIRCLSFileManager; + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRCLSSettings : NSObject + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + NS_DESIGNATED_INITIALIZER; + +/** + * Recreates the settings dictionary by re-reading the settings file from persistent storage. This + * should be called before any settings values are read, as it will populate the underlying + * settingsDictionary. If the Google App ID has changed or there is an error, delete the cache file + * and settingsDictionary. If the cache has expired, set `isCacheExpired` to true so that settings + * are re-fetched, but do not delete any values. + */ +- (void)reloadFromCacheWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp; + +/** + * Stores a separate file with the settings expiration and Google App ID it was saved with + * so that we can later determine that the settings have expired. + * + * This should be called in a background thread right after the settings.json file has been + * downloaded. + */ +- (void)cacheSettingsWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp; + +/** + * Returns true when Settings should be fetched from the server again + */ +@property(nonatomic, readonly) BOOL isCacheExpired; + +/** + * Determines how long these Settings should be respected until the SDK should fetch again + */ +@property(nonatomic, readonly) uint32_t cacheDurationSeconds; + +/** + * The Crashlytics Organization identifier of the app. Allows data continuity between + * old and new Crashlytics SDKs. + */ +@property(nonatomic, nullable, readonly) NSString *orgID; + +/** + * The backend bundle identifier of the app. Crashlytics can in some cases have + * a different bundle identifier than the app itself (eg. Crashlytics will always downcase + * the bundle ID). + */ +@property(nonatomic, nullable, readonly) NSString *fetchedBundleID; + +/** + * Indicates whether the app needs onboarding + */ +@property(nonatomic, readonly) BOOL appNeedsOnboarding; + +/** + * Indicates whether the app needs an update + */ +@property(nonatomic, readonly) BOOL appUpdateRequired; + +/** + * When this is false, Crashlytics will not start up + */ +@property(nonatomic, readonly) BOOL collectReportsEnabled; + +/** + * When this is false, Crashlytics will not collect non-fatal errors and errors + * from the custom exception / record error APIs + */ +@property(nonatomic, readonly) BOOL errorReportingEnabled; + +/** + * When this is false, Crashlytics will not collect custom exceptions from the API + */ +@property(nonatomic, readonly) BOOL customExceptionsEnabled; + +/** + * Determine if the SDK should use the new endpoint for uploading reports + */ +@property(nonatomic, readonly) BOOL shouldUseNewReportEndpoint; + +/** + * Returns the maximum number of custom exception events that will be + * recorded in a session. + */ +@property(nonatomic, readonly) uint32_t errorLogBufferSize; + +/** + * Returns the maximum size of the log buffer in bytes + */ +@property(nonatomic, readonly) uint32_t logBufferSize; + +/** + * Returns the maximum number of custom exceptions that will be collected + * in a session. + */ +@property(nonatomic, readonly) uint32_t maxCustomExceptions; + +/** + * Returns the maximum number of custom key-value pair keys (not bytes). + */ +@property(nonatomic, readonly) uint32_t maxCustomKeys; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.m new file mode 100644 index 00000000..a5219cad --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSettings.m @@ -0,0 +1,357 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" +#import "Crashlytics/Shared/FIRCLSConstants.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h" + +NSString *const CreatedAtKey = @"created_at"; +NSString *const GoogleAppIDKey = @"google_app_id"; +NSString *const BuildInstanceID = @"build_instance_id"; +NSString *const AppVersion = @"app_version"; + +@interface FIRCLSSettings () + +@property(nonatomic, strong) FIRCLSFileManager *fileManager; +@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel; + +@property(nonatomic, strong) NSDictionary<NSString *, id> *settingsDictionary; + +@property(nonatomic) BOOL isCacheKeyExpired; + +@end + +@implementation FIRCLSSettings + +- (instancetype)initWithFileManager:(FIRCLSFileManager *)fileManager + appIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel { + self = [super init]; + if (!self) { + return nil; + } + + _fileManager = fileManager; + _appIDModel = appIDModel; + + _settingsDictionary = nil; + _isCacheKeyExpired = NO; + + return self; +} + +#pragma mark - Public Methods + +- (void)reloadFromCacheWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp { + NSString *settingsFilePath = self.fileManager.settingsFilePath; + + NSData *data = [self.fileManager dataWithContentsOfFile:settingsFilePath]; + + if (!data) { + FIRCLSDebugLog(@"[Crashlytics:Settings] No settings were cached"); + + return; + } + + NSError *error = nil; + @synchronized(self) { + _settingsDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; + } + + if (!_settingsDictionary) { + FIRCLSErrorLog(@"Could not load settings file data with error: %@", error.localizedDescription); + + // Attempt to remove it, in case it's messed up + [self deleteCachedSettings]; + return; + } + + NSDictionary<NSString *, id> *cacheKey = [self loadCacheKey]; + if (!cacheKey) { + FIRCLSErrorLog(@"Could not load settings cache key"); + + [self deleteCachedSettings]; + return; + } + + NSString *cachedGoogleAppID = cacheKey[GoogleAppIDKey]; + if (![cachedGoogleAppID isEqualToString:googleAppID]) { + FIRCLSDebugLog( + @"[Crashlytics:Settings] Invalidating settings cache because Google App ID changed"); + + [self deleteCachedSettings]; + return; + } + + NSTimeInterval cacheCreatedAt = [cacheKey[CreatedAtKey] unsignedIntValue]; + NSTimeInterval cacheDurationSeconds = self.cacheDurationSeconds; + if (currentTimestamp > (cacheCreatedAt + cacheDurationSeconds)) { + FIRCLSDebugLog(@"[Crashlytics:Settings] Settings TTL expired"); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + } + } + + NSString *cacheBuildInstanceID = cacheKey[BuildInstanceID]; + if (![cacheBuildInstanceID isEqualToString:self.appIDModel.buildInstanceID]) { + FIRCLSDebugLog(@"[Crashlytics:Settings] Settings expired because build instance changed"); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + } + } + + NSString *cacheAppVersion = cacheKey[AppVersion]; + if (![cacheAppVersion isEqualToString:self.appIDModel.synthesizedVersion]) { + FIRCLSDebugLog(@"[Crashlytics:Settings] Settings expired because app version changed"); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + } + } +} + +- (void)cacheSettingsWithGoogleAppID:(NSString *)googleAppID + currentTimestamp:(NSTimeInterval)currentTimestamp { + NSNumber *createdAtTimestamp = [NSNumber numberWithDouble:currentTimestamp]; + NSDictionary *cacheKey = @{ + CreatedAtKey : createdAtTimestamp, + GoogleAppIDKey : googleAppID, + BuildInstanceID : self.appIDModel.buildInstanceID, + AppVersion : self.appIDModel.synthesizedVersion, + }; + + NSError *error = nil; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:cacheKey + options:kNilOptions + error:&error]; + + if (!jsonData) { + FIRCLSErrorLog(@"Could not create settings cache key with error: %@", + error.localizedDescription); + + return; + } + + if ([self.fileManager fileExistsAtPath:self.fileManager.settingsCacheKeyPath]) { + [self.fileManager removeItemAtPath:self.fileManager.settingsCacheKeyPath]; + } + [self.fileManager createFileAtPath:self.fileManager.settingsCacheKeyPath + contents:jsonData + attributes:nil]; + + // If Settings were expired before, they should no longer be expired after this. + // This may be set back to YES if reloading from the cache fails + @synchronized(self) { + self.isCacheKeyExpired = NO; + } + + [self reloadFromCacheWithGoogleAppID:googleAppID currentTimestamp:currentTimestamp]; +} + +#pragma mark - Convenience Methods + +- (NSDictionary *)loadCacheKey { + NSData *cacheKeyData = + [self.fileManager dataWithContentsOfFile:self.fileManager.settingsCacheKeyPath]; + + if (!cacheKeyData) { + return nil; + } + + NSError *error = nil; + NSDictionary *cacheKey = [NSJSONSerialization JSONObjectWithData:cacheKeyData + options:NSJSONReadingAllowFragments + error:&error]; + return cacheKey; +} + +- (void)deleteCachedSettings { + __weak FIRCLSSettings *weakSelf = self; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ + __strong FIRCLSSettings *strongSelf = weakSelf; + if ([strongSelf.fileManager fileExistsAtPath:strongSelf.fileManager.settingsFilePath]) { + [strongSelf.fileManager removeItemAtPath:strongSelf.fileManager.settingsFilePath]; + } + if ([strongSelf.fileManager fileExistsAtPath:strongSelf.fileManager.settingsCacheKeyPath]) { + [strongSelf.fileManager removeItemAtPath:strongSelf.fileManager.settingsCacheKeyPath]; + } + }); + + @synchronized(self) { + self.isCacheKeyExpired = YES; + _settingsDictionary = nil; + } +} + +- (NSDictionary<NSString *, id> *)settingsDictionary { + @synchronized(self) { + return _settingsDictionary; + } +} + +#pragma mark - Settings Groups + +- (NSDictionary<NSString *, id> *)appSettings { + return self.settingsDictionary[@"app"]; +} + +- (NSDictionary<NSString *, id> *)sessionSettings { + return self.settingsDictionary[@"session"]; +} + +- (NSDictionary<NSString *, id> *)featuresSettings { + return self.settingsDictionary[@"features"]; +} + +- (NSDictionary<NSString *, id> *)fabricSettings { + return self.settingsDictionary[@"fabric"]; +} + +#pragma mark - Caching + +- (BOOL)isCacheExpired { + if (!self.settingsDictionary) { + return YES; + } + + @synchronized(self) { + return self.isCacheKeyExpired; + } +} + +- (uint32_t)cacheDurationSeconds { + id fetchedCacheDuration = self.settingsDictionary[@"cache_duration"]; + if (fetchedCacheDuration) { + return [fetchedCacheDuration unsignedIntValue]; + } + + return 60 * 60; +} + +#pragma mark - Identifiers + +- (nullable NSString *)orgID { + return self.fabricSettings[@"org_id"]; +} + +- (nullable NSString *)fetchedBundleID { + return self.fabricSettings[@"bundle_id"]; +} + +#pragma mark - Onboarding / Update + +- (NSString *)appStatus { + return self.appSettings[@"status"]; +} + +- (BOOL)appNeedsOnboarding { + return [self.appStatus isEqualToString:@"new"]; +} + +- (BOOL)appUpdateRequired { + return [[self.appSettings objectForKey:@"update_required"] boolValue]; +} + +#pragma mark - On / Off Switches + +- (BOOL)errorReportingEnabled { + NSNumber *value = [self featuresSettings][@"collect_logged_exceptions"]; + + if (value != nil) { + return [value boolValue]; + } + + return YES; +} + +- (BOOL)customExceptionsEnabled { + // Right now, recording custom exceptions from the API and + // automatically capturing non-fatal errors go hand in hand + return [self errorReportingEnabled]; +} + +- (BOOL)collectReportsEnabled { + NSNumber *value = [self featuresSettings][@"collect_reports"]; + + if (value != nil) { + return value.boolValue; + } + + return YES; +} + +- (BOOL)shouldUseNewReportEndpoint { + NSNumber *value = [self appSettings][@"report_upload_variant"]; + + // Default to use the new endpoint when settings were not successfully fetched + // or there's an unexpected issue + if (value == nil) { + return YES; + } + + // 0 - Unknown + // 1 - Legacy + // 2 - New + return value.intValue == 2; +} + +#pragma mark - Optional Limit Overrides + +- (uint32_t)errorLogBufferSize { + return [self logBufferSize]; +} + +- (uint32_t)logBufferSize { + NSNumber *value = [self sessionSettings][@"log_buffer_size"]; + + if (value != nil) { + return value.unsignedIntValue; + } + + return 64 * 1000; +} + +- (uint32_t)maxCustomExceptions { + NSNumber *value = [self sessionSettings][@"max_custom_exception_events"]; + + if (value != nil) { + return value.unsignedIntValue; + } + + return 8; +} + +- (uint32_t)maxCustomKeys { + NSNumber *value = [self sessionSettings][@"max_custom_key_value_pairs"]; + + if (value != nil) { + return value.unsignedIntValue; + } + + return 64; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h new file mode 100644 index 00000000..a18e6046 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h @@ -0,0 +1,26 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRStackFrame; + +@interface FIRCLSSymbolResolver : NSObject + +- (BOOL)loadBinaryImagesFromFile:(NSString *)path; + +- (FIRStackFrame *)frameForAddress:(uint64_t)address; +- (BOOL)updateStackFrame:(FIRStackFrame *)frame; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.m new file mode 100644 index 00000000..9a5570ef --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.m @@ -0,0 +1,175 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h" + +#include <dlfcn.h> + +#include "Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h" + +@interface FIRCLSSymbolResolver () { + NSMutableArray* _binaryImages; +} + +@end + +@implementation FIRCLSSymbolResolver + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _binaryImages = [NSMutableArray array]; + + return self; +} + +- (BOOL)loadBinaryImagesFromFile:(NSString*)path { + if ([path length] == 0) { + return NO; + } + + NSArray* sections = FIRCLSFileReadSections([path fileSystemRepresentation], false, nil); + + if ([sections count] == 0) { + FIRCLSErrorLog(@"Failed to read binary image file %@", path); + return NO; + } + + // filter out unloads, as well as loads with invalid entries + for (NSDictionary* entry in sections) { + NSDictionary* details = [entry objectForKey:@"load"]; + if (!details) { + continue; + } + + // This does happen occationally and causes a crash. I'm really not sure there + // is anything sane we can do in this case. + if (![details objectForKey:@"base"] || ![details objectForKey:@"size"]) { + continue; + } + + if ([details objectForKey:@"base"] == (id)[NSNull null] || + [details objectForKey:@"size"] == (id)[NSNull null]) { + continue; + } + + [_binaryImages addObject:details]; + } + + [_binaryImages sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { + NSNumber* base1 = [obj1 objectForKey:@"base"]; + NSNumber* base2 = [obj2 objectForKey:@"base"]; + + return [base1 compare:base2]; + }]; + + return YES; +} + +- (NSDictionary*)loadedBinaryImageForPC:(uintptr_t)pc { + NSUInteger index = + [_binaryImages indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL* stop) { + uintptr_t base = [[obj objectForKey:@"base"] unsignedIntegerValue]; + uintptr_t size = [[obj objectForKey:@"size"] unsignedIntegerValue]; + + return pc >= base && pc < (base + size); + }]; + + if (index == NSNotFound) { + return nil; + } + + return [_binaryImages objectAtIndex:index]; +} + +- (BOOL)fillInImageDetails:(FIRCLSBinaryImageDetails*)details forUUID:(NSString*)uuid { + if (!details || !uuid) { + return NO; + } + + return FIRCLSBinaryImageFindImageForUUID([uuid UTF8String], details); +} + +- (FIRStackFrame*)frameForAddress:(uint64_t)address { + FIRStackFrame* frame = [FIRStackFrame stackFrameWithAddress:(NSUInteger)address]; + + if (![self updateStackFrame:frame]) { + return nil; + } + + return frame; +} + +- (BOOL)updateStackFrame:(FIRStackFrame*)frame { + uint64_t address = [frame address]; + if (address == 0) { + return NO; + } + + NSDictionary* binaryImage = [self loadedBinaryImageForPC:(uintptr_t)address]; + + FIRCLSBinaryImageDetails imageDetails; + + if (![self fillInImageDetails:&imageDetails forUUID:[binaryImage objectForKey:@"uuid"]]) { +#if DEBUG + FIRCLSDebugLog(@"Image not found"); +#endif + return NO; + } + + uintptr_t addr = (uintptr_t)address - + (uintptr_t)[[binaryImage objectForKey:@"base"] unsignedIntegerValue] + + (uintptr_t)imageDetails.node.baseAddress; + Dl_info dlInfo; + + if (dladdr((void*)addr, &dlInfo) == 0) { +#if DEBUG + FIRCLSDebugLog(@"Could not look up address"); +#endif + return NO; + } + + if (addr - (uintptr_t)dlInfo.dli_saddr == 0) { + addr -= 2; + if (dladdr((void*)addr, &dlInfo) == 0) { +#if DEBUG + FIRCLSDebugLog(@"Could not look up address"); +#endif + return NO; + } + } + + if (dlInfo.dli_sname) { + NSString* symbol = [NSString stringWithUTF8String:dlInfo.dli_sname]; + + frame.symbol = symbol; + frame.rawSymbol = symbol; + } + + if (addr > (uintptr_t)dlInfo.dli_saddr) { + [frame setOffset:addr - (uintptr_t)dlInfo.dli_saddr]; + } + + [frame setLibrary:[[binaryImage objectForKey:@"path"] lastPathComponent]]; + + return YES; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h new file mode 100644 index 00000000..a3177b2c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h" + +@interface FIRCLSRecordApplication : FIRCLSRecordBase + +@property(nonatomic, copy) NSString *build_version; +@property(nonatomic, copy) NSString *display_version; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.m new file mode 100644 index 00000000..b4474165 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.m @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h" + +@implementation FIRCLSRecordApplication + +- (instancetype)initWithDict:(NSDictionary *)dict { + self = [super initWithDict:dict]; + if (self) { + _display_version = dict[@"display_version"]; + _build_version = dict[@"build_version"]; + } + return self; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h new file mode 100644 index 00000000..624c5577 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import <Foundation/Foundation.h> + +/** + * This is the base class to represent the data in the persisted crash (.clsrecord) files. + * The properties these subclasses are nullable on purpose. If there is an issue reading values + * from the crash files, continue as if those fields are optional so a report can still be uploaded. + * That way the issue can potentially be monitored through the backend. + **/ +@interface FIRCLSRecordBase : NSObject + +/** + * Mark the default initializer as unavailable so the subclasses do not have to add the same line + **/ +- (instancetype)init NS_UNAVAILABLE; + +/** + * All subclasses should define an initializer taking in a dictionary + **/ +- (instancetype)initWithDict:(NSDictionary *)dict; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.m new file mode 100644 index 00000000..9b07ffe6 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.m @@ -0,0 +1,25 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h" + +@implementation FIRCLSRecordBase + +- (instancetype)initWithDict:(NSDictionary *)dict { + return [super init]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h new file mode 100644 index 00000000..a1a18bc5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h" + +@interface FIRCLSRecordHost : FIRCLSRecordBase + +@property(nonatomic, copy) NSString *platform; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.m new file mode 100644 index 00000000..dd678a00 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.m @@ -0,0 +1,29 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h" + +@implementation FIRCLSRecordHost + +- (instancetype)initWithDict:(NSDictionary *)dict { + self = [super initWithDict:dict]; + if (self) { + _platform = dict[@"platform"]; + } + return self; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h new file mode 100644 index 00000000..8aa2602b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h @@ -0,0 +1,24 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordBase.h" + +@interface FIRCLSRecordIdentity : FIRCLSRecordBase + +@property(nonatomic, copy) NSString *build_version; +@property(nonatomic, copy) NSString *install_id; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.m new file mode 100644 index 00000000..3bbc7e9a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.m @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h" + +@implementation FIRCLSRecordIdentity + +- (instancetype)initWithDict:(NSDictionary *)dict { + self = [super initWithDict:dict]; + if (self) { + _build_version = dict[@"build_version"]; + _install_id = dict[@"install_id"]; + } + return self; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h new file mode 100644 index 00000000..3f29f643 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import <Foundation/Foundation.h> + +#include "Crashlytics/Protogen/nanopb/crashlytics.nanopb.h" + +#import "GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h" + +/// This class is responsible for reading the persisted crash reports from disk and converting them +/// the information into the nanopb model to be used with GoogleDataTransport +@interface FIRCLSReportAdapter : NSObject <GDTCOREventDataObject> + +- (instancetype)init NS_UNAVAILABLE; + +/// Initializer +/// @param folderPath Path where the persisted crash files reside +- (instancetype)initWithPath:(NSString *)folderPath googleAppId:(NSString *)googleAppID; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m new file mode 100644 index 00000000..768e1e6e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.m @@ -0,0 +1,254 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h" +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSUserLogging.h" + +#if SWIFT_PACKAGE +@import nanopb; +#else +#import <nanopb/pb.h> +#import <nanopb/pb_decode.h> +#import <nanopb/pb_encode.h> +#endif + +@implementation FIRCLSReportAdapter + +- (instancetype)initWithPath:(NSString *)folderPath googleAppId:(NSString *)googleAppID { + self = [super init]; + if (self) { + _folderPath = folderPath; + _googleAppID = googleAppID; + + [self loadMetaDataFile]; + + _report = [self protoReport]; + } + return self; +} + +- (void)dealloc { + pb_release(google_crashlytics_Report_fields, &_report); +} + +// +// MARK: Load from persisted crash files +// + +/// Reads from metadata.clsrecord +- (void)loadMetaDataFile { + NSString *path = [self.folderPath stringByAppendingPathComponent:FIRCLSReportMetadataFile]; + NSDictionary *dict = [FIRCLSReportAdapter combinedDictionariesFromFilePath:path]; + + self.identity = [[FIRCLSRecordIdentity alloc] initWithDict:dict[@"identity"]]; + self.host = [[FIRCLSRecordHost alloc] initWithDict:dict[@"host"]]; + self.application = [[FIRCLSRecordApplication alloc] initWithDict:dict[@"application"]]; +} + +/// Return the persisted crash file as a combined dictionary that way lookups can occur with a key +/// (to avoid ordering dependency) +/// @param filePath Persisted crash file path ++ (NSDictionary *)combinedDictionariesFromFilePath:(NSString *)filePath { + NSMutableDictionary *joinedDict = [[NSMutableDictionary alloc] init]; + for (NSDictionary *dict in [self dictionariesFromEachLineOfFile:filePath]) { + [joinedDict addEntriesFromDictionary:dict]; + } + return joinedDict; +} + +/// The persisted crash files contains JSON on separate lines. Read each line and return the JSON +/// data as a dictionary. +/// @param filePath Persisted crash file path ++ (NSArray<NSDictionary *> *)dictionariesFromEachLineOfFile:(NSString *)filePath { + NSString *content = [[NSString alloc] initWithContentsOfFile:filePath + encoding:NSUTF8StringEncoding + error:nil]; + NSArray *lines = + [content componentsSeparatedByCharactersInSet:NSCharacterSet.newlineCharacterSet]; + + NSMutableArray<NSDictionary *> *array = [[NSMutableArray<NSDictionary *> alloc] init]; + + int lineNum = 0; + for (NSString *line in lines) { + lineNum++; + + if (line.length == 0) { + // Likely newline at the end of the file + continue; + } + + NSError *error; + NSDictionary *dict = + [NSJSONSerialization JSONObjectWithData:[line dataUsingEncoding:NSUTF8StringEncoding] + options:0 + error:&error]; + + if (error) { + FIRCLSErrorLog(@"Failed to read JSON from file (%@) line (%d) with error: %@", filePath, + lineNum, error); + } else { + [array addObject:dict]; + } + } + + return array; +} + +// +// MARK: GDTCOREventDataObject +// + +- (NSData *)transportBytes { + pb_ostream_t sizestream = PB_OSTREAM_SIZING; + + // Encode 1 time to determine the size. + if (!pb_encode(&sizestream, google_crashlytics_Report_fields, &_report)) { + FIRCLSErrorLog(@"Error in nanopb encoding for size: %s", PB_GET_ERROR(&sizestream)); + } + + // Encode a 2nd time to actually get the bytes from it. + size_t bufferSize = sizestream.bytes_written; + CFMutableDataRef dataRef = CFDataCreateMutable(CFAllocatorGetDefault(), bufferSize); + CFDataSetLength(dataRef, bufferSize); + pb_ostream_t ostream = pb_ostream_from_buffer((void *)CFDataGetBytePtr(dataRef), bufferSize); + if (!pb_encode(&ostream, google_crashlytics_Report_fields, &_report)) { + FIRCLSErrorLog(@"Error in nanopb encoding for bytes: %s", PB_GET_ERROR(&ostream)); + } + + return CFBridgingRelease(dataRef); +} + +// +// MARK: NanoPB conversions +// + +- (google_crashlytics_Report)protoReport { + google_crashlytics_Report report = google_crashlytics_Report_init_default; + report.sdk_version = FIRCLSEncodeString(self.identity.build_version); + report.gmp_app_id = FIRCLSEncodeString(self.googleAppID); + report.platform = [self protoPlatformFromString:self.host.platform]; + report.installation_uuid = FIRCLSEncodeString(self.identity.install_id); + report.build_version = FIRCLSEncodeString(self.application.build_version); + report.display_version = FIRCLSEncodeString(self.application.display_version); + report.apple_payload = [self protoFilesPayload]; + return report; +} + +- (google_crashlytics_FilesPayload)protoFilesPayload { + google_crashlytics_FilesPayload apple_payload = google_crashlytics_FilesPayload_init_default; + + NSArray<NSString *> *clsRecords = [self clsRecordFilePaths]; + google_crashlytics_FilesPayload_File *files = + malloc(sizeof(google_crashlytics_FilesPayload_File) * clsRecords.count); + + if (files == NULL) { + // files and files_count are initialized to NULL and 0 by default. + return apple_payload; + } + for (NSUInteger i = 0; i < clsRecords.count; i++) { + google_crashlytics_FilesPayload_File file = google_crashlytics_FilesPayload_File_init_default; + file.filename = FIRCLSEncodeString(clsRecords[i].lastPathComponent); + + NSError *error; + file.contents = FIRCLSEncodeData([NSData dataWithContentsOfFile:clsRecords[i] + options:0 + error:&error]); + if (error) { + FIRCLSErrorLog(@"Failed to read from %@ with error: %@", clsRecords[i], error); + } + + files[i] = file; + } + + apple_payload.files = files; + apple_payload.files_count = (pb_size_t)clsRecords.count; + + return apple_payload; +} + +- (NSArray<NSString *> *)clsRecordFilePaths { + NSMutableArray<NSString *> *clsRecords = [[NSMutableArray<NSString *> alloc] init]; + + NSError *error; + NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.folderPath + error:&error]; + + if (error) { + FIRCLSErrorLog(@"Failed to find .clsrecords from %@ with error: %@", self.folderPath, error); + return clsRecords; + } + + [files enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + NSString *filename = (NSString *)obj; + NSString *lowerExtension = filename.pathExtension.lowercaseString; + if ([lowerExtension isEqualToString:@"clsrecord"] || + [lowerExtension isEqualToString:@"symbolicated"]) { + [clsRecords addObject:[self.folderPath stringByAppendingPathComponent:filename]]; + } + }]; + + return [clsRecords sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; +} + +- (google_crashlytics_Platforms)protoPlatformFromString:(NSString *)str { + NSString *platform = str.lowercaseString; + + if ([platform isEqualToString:@"ios"]) { + return google_crashlytics_Platforms_IOS; + } else if ([platform isEqualToString:@"mac"]) { + return google_crashlytics_Platforms_MAC_OS_X; + } else if ([platform isEqualToString:@"tvos"]) { + return google_crashlytics_Platforms_TVOS; + } else { + return google_crashlytics_Platforms_UNKNOWN_PLATFORM; + } +} + +/** Mallocs a pb_bytes_array and copies the given NSString's bytes into the bytes array. + * @note Memory needs to be freed manually, through pb_free or pb_release. + * @param string The string to encode as pb_bytes. + */ +pb_bytes_array_t *FIRCLSEncodeString(NSString *string) { + if ([string isMemberOfClass:[NSNull class]]) { + FIRCLSErrorLog(@"Expected encodable string, but found NSNull instead. " + @"Set a symbolic breakpoint at FIRCLSEncodeString to debug."); + string = nil; + } + NSString *stringToEncode = string ? string : @""; + NSData *stringBytes = [stringToEncode dataUsingEncoding:NSUTF8StringEncoding]; + return FIRCLSEncodeData(stringBytes); +} + +/** Mallocs a pb_bytes_array and copies the given NSData bytes into the bytes array. + * @note Memory needs to be free manually, through pb_free or pb_release. + * @param data The data to copy into the new bytes array. + */ +pb_bytes_array_t *FIRCLSEncodeData(NSData *data) { + pb_bytes_array_t *pbBytes = malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(data.length)); + if (pbBytes == NULL) { + return NULL; + } + memcpy(pbBytes->bytes, [data bytes], data.length); + pbBytes->size = (pb_size_t)data.length; + return pbBytes; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h new file mode 100644 index 00000000..809e08de --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter_Private.h @@ -0,0 +1,43 @@ +/* + * Copyright 2020 Google LLC + * + * 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. + */ + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSReportAdapter.h" + +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordApplication.h" +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordHost.h" +#import "Crashlytics/Crashlytics/Models/Record/FIRCLSRecordIdentity.h" + +pb_bytes_array_t *FIRCLSEncodeString(NSString *string); +pb_bytes_array_t *FIRCLSEncodeData(NSData *data); + +@interface FIRCLSReportAdapter () + +@property(nonatomic, readonly) BOOL hasCrashed; + +@property(nonatomic, strong) NSString *folderPath; +@property(nonatomic, strong) NSString *googleAppID; + +// From metadata.clsrecord +@property(nonatomic, strong) FIRCLSRecordIdentity *identity; +@property(nonatomic, strong) FIRCLSRecordHost *host; +@property(nonatomic, strong) FIRCLSRecordApplication *application; + +@property(nonatomic) google_crashlytics_Report report; + +- (google_crashlytics_Report)protoReport; +- (NSArray<NSString *> *)clsRecordFilePaths; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h new file mode 100644 index 00000000..5636d3d0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +typedef void (^FIRCLSAsyncOperationCompletionBlock)(NSError* error); + +@interface FIRCLSAsyncOperation : NSOperation + +@property(copy, nonatomic) FIRCLSAsyncOperationCompletionBlock asyncCompletion; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.m new file mode 100644 index 00000000..1ec49e4e --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.m @@ -0,0 +1,135 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h" + +@interface FIRCLSAsyncOperation () { + BOOL _internalExecuting; + BOOL _internalFinished; +} + +@property(nonatomic, strong) NSRecursiveLock *lock; + +@end + +@implementation FIRCLSAsyncOperation + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _internalExecuting = NO; + _internalFinished = NO; + + self.lock = [[NSRecursiveLock alloc] init]; + self.lock.name = @"com.crashlytics.async-operation-lock"; + + return self; +} + +#pragma mark - NSOperation Overrides +- (BOOL)isConcurrent { + return YES; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + [self.lock lock]; + BOOL result = _internalExecuting; + [self.lock unlock]; + + return result; +} + +- (BOOL)isFinished { + [self.lock lock]; + BOOL result = _internalFinished; + [self.lock unlock]; + + return result; +} + +- (void)start { + if ([self checkForCancellation]) { + return; + } + + [self markStarted]; + + [self main]; +} + +#pragma mark - Utilities +- (void)changeValueForKey:(NSString *)key inBlock:(void (^)(void))block { + [self willChangeValueForKey:key]; + block(); + [self didChangeValueForKey:key]; +} + +- (void)lock:(void (^)(void))block { + [self.lock lock]; + block(); + [self.lock unlock]; +} + +- (BOOL)checkForCancellation { + if ([self isCancelled]) { + [self markDone]; + return YES; + } + + return NO; +} + +#pragma mark - State Management +- (void)unlockedMarkFinished { + [self changeValueForKey:@"isFinished" + inBlock:^{ + self->_internalFinished = YES; + }]; +} + +- (void)unlockedMarkStarted { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = YES; + }]; +} + +- (void)unlockedMarkComplete { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = NO; + }]; +} + +- (void)markStarted { + [self lock:^{ + [self unlockedMarkStarted]; + }]; +} + +- (void)markDone { + [self lock:^{ + [self unlockedMarkComplete]; + [self unlockedMarkFinished]; + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h new file mode 100644 index 00000000..6dcc7076 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation_Private.h @@ -0,0 +1,24 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/FIRCLSAsyncOperation.h" + +@interface FIRCLSAsyncOperation (Private) + +- (void)markStarted; +- (void)markDone; + +- (BOOL)checkForCancellation; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h new file mode 100644 index 00000000..5822e752 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h @@ -0,0 +1,35 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRCLSInternalReport; +@class FIRCLSFileManager; +@class FIRCLSSettings; + +@interface FIRCLSPackageReportOperation : NSOperation + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + fileManager:(FIRCLSFileManager *)fileManager + settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, readonly) FIRCLSInternalReport *report; +@property(nonatomic, readonly) FIRCLSFileManager *fileManager; +@property(nonatomic, readonly) FIRCLSSettings *settings; + +@property(nonatomic, copy, readonly) NSString *finalPath; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.m new file mode 100644 index 00000000..efd59198 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.m @@ -0,0 +1,210 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Reports/FIRCLSPackageReportOperation.h" + +#include <errno.h> +#include <zlib.h> + +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h" + +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" + +@interface FIRCLSPackageReportOperation () + +@property(nonatomic, copy) NSString *finalPath; + +@end + +@implementation FIRCLSPackageReportOperation + +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + fileManager:(FIRCLSFileManager *)fileManager + settings:(FIRCLSSettings *)settings { + self = [super init]; + if (!self) { + return nil; + } + + _report = report; + _fileManager = fileManager; + _settings = settings; + + return self; +} + +- (BOOL)compressData:(NSData *)data toPath:(NSString *)path { + gzFile file = gzopen([path fileSystemRepresentation], "w"); + if (file == Z_NULL) { + FIRCLSSDKLogError("Error: unable to open file for compression %s\n", strerror(errno)); + return NO; + } + + __block BOOL success = [data length] > 0; + + FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + data, ^(const void *bytes, NSRange byteRange, BOOL *stop) { + size_t length = byteRange.length; + + if (![self writeBytes:bytes length:length toGZFile:file]) { + *stop = YES; + success = NO; + } + }); + + gzclose(file); + + return success; +} + +- (BOOL)writeBytes:(const void *)buffer length:(size_t)length toGZFile:(gzFile)file { + return FIRCLSFileLoopWithWriteBlock( + buffer, length, ^ssize_t(const void *partialBuffer, size_t partialLength) { + errno = 0; + int ret = gzwrite(file, buffer, (unsigned int)length); + + if (ret == 0) { + int zerror = 0; + const char *errorString = gzerror(file, &zerror); + + FIRCLSSDKLogError("Error: failed to write compressed bytes %d, %s, %s \n", zerror, + errorString, strerror(errno)); + } + + return ret; + }); +} + +- (NSString *)reportPath { + return [self.report path]; +} + +- (NSString *)destinationDirectory { + return [self.fileManager legacyPreparedPath]; +} + +- (NSString *)packagedPathWithName:(NSString *)name { + // the output file will use the boundary as the filename, and "multipartmime" as the extension + return [[self.destinationDirectory stringByAppendingPathComponent:name] + stringByAppendingPathExtension:@"multipartmime"]; +} + +- (void)main { + NSString *reportOrgID = self.settings.orgID; + if (!reportOrgID) { + FIRCLSDebugLog( + @"[Crashlytics:PackageReport] Skipping packaging of report with id '%@' this run of the " + @"app because Organization ID was nil. Report will upload once settings are download " + @"successfully", + self.report.identifier); + + return; + } + + self.finalPath = nil; + + NSString *boundary = [FIRCLSMultipartMimeStreamEncoder generateBoundary]; + NSString *destPath = [self packagedPathWithName:boundary]; + + // try to read the metadata file, which could always fail + NSString *reportSessionId = self.report.identifier; + + NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:destPath append:NO]; + + FIRCLSMultipartMimeStreamEncoder *encoder = + [FIRCLSMultipartMimeStreamEncoder encoderWithStream:stream andBoundary:boundary]; + if (!encoder) { + return; + } + + [encoder encode:^{ + [encoder addValue:reportOrgID fieldName:@"org_id"]; + + if (reportSessionId) { + [encoder addValue:reportSessionId fieldName:@"report_id"]; + } + + [self.fileManager + enumerateFilesInDirectory:self.reportPath + usingBlock:^(NSString *filePath, NSString *extension) { + if (self.cancelled) { + return; + } + + // Do not package or include already gz'ed files. These can get left over + // from previously-submitted reports. There's an opportinity here to avoid + // compressed certain types of files that cannot be changed. + if ([extension isEqualToString:@"gz"]) { + return; + } + + NSData *data = [NSData dataWithContentsOfFile:filePath + options:0 + error:nil]; + if ([data length] == 0) { + const char *filename = [[filePath lastPathComponent] UTF8String]; + + FIRCLSSDKLogError("Error: unable to read data for compression: %s\n", + filename); + return; + } + + [self encode:encoder data:data fromPath:filePath]; + }]; + }]; + + if (self.cancelled) { + [self.fileManager removeItemAtPath:destPath]; + return; + } + + self.finalPath = destPath; +} + +- (void)encode:(FIRCLSMultipartMimeStreamEncoder *)encoder + data:(NSData *)data + fromPath:(NSString *)path { + // must be non-nil and > 0 length + if ([path length] == 0) { + FIRCLSSDKLogError("Error: path is invalid\n"); + return; + } + + NSString *uploadPath = [path stringByAppendingPathExtension:@"gz"]; + NSString *fieldname = [path lastPathComponent]; + NSString *filename = [uploadPath lastPathComponent]; + NSString *mimeType = @"application/x-gzip"; + + // first, attempt to compress + if (![self compressData:data toPath:uploadPath]) { + FIRCLSSDKLogError("Error: compression failed for %s\n", [filename UTF8String]); + + // attempt the upload without compression + mimeType = @"text/plain"; + uploadPath = path; + } + + [encoder addFile:[NSURL fileURLWithPath:uploadPath] + fileName:filename + mimeType:mimeType + fieldName:fieldname]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h new file mode 100644 index 00000000..1e902863 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h @@ -0,0 +1,30 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRCLSInternalReport; +@class FIRCLSSymbolResolver; + +@interface FIRCLSProcessReportOperation : NSOperation + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + resolver:(FIRCLSSymbolResolver *)resolver NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, readonly) FIRCLSSymbolResolver *symbolResolver; +@property(nonatomic, readonly) FIRCLSInternalReport *report; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.m new file mode 100644 index 00000000..03a7c1e9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.m @@ -0,0 +1,113 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Reports/FIRCLSProcessReportOperation.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInternalReport.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h" +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h" +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h" +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h" +#import "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h" + +@implementation FIRCLSProcessReportOperation + +- (instancetype)initWithReport:(FIRCLSInternalReport *)report + resolver:(FIRCLSSymbolResolver *)resolver { + self = [super init]; + if (!self) { + return nil; + } + + _report = report; + _symbolResolver = resolver; + + return self; +} + +- (NSString *)binaryImagePath { + return self.report.binaryImagePath; +} + +- (NSArray *)threadArrayFromFile:(NSString *)path { + NSArray *threads = + FIRCLSFileReadSections([path fileSystemRepresentation], false, ^NSObject *(id obj) { + // use this to select out the one entry that has a "threads" top-level entry + return [obj objectForKey:@"threads"]; + }); + + if ([threads count] == 0) { + return nil; + } + + // threads is actually an array of arrays + threads = [threads objectAtIndex:0]; + if (!threads) { + return nil; + } + + NSMutableArray *threadArray = [NSMutableArray array]; + + for (NSDictionary *threadDetails in threads) { + NSMutableArray *frameArray = [NSMutableArray array]; + + for (NSNumber *pc in [threadDetails objectForKey:@"stacktrace"]) { + FIRStackFrame *frame = [FIRStackFrame stackFrameWithAddress:[pc unsignedIntegerValue]]; + + [frameArray addObject:frame]; + } + + [threadArray addObject:frameArray]; + } + + return threadArray; +} + +- (BOOL)symbolicateFile:(NSString *)path withResolver:(FIRCLSSymbolResolver *)resolver { + NSArray *threadArray = [self threadArrayFromFile:path]; + if (!threadArray) { + return NO; + } + + FIRCLSSymbolicationOperation *symbolicationOp = [[FIRCLSSymbolicationOperation alloc] init]; + [symbolicationOp setThreadArray:threadArray]; + [symbolicationOp setSymbolResolver:resolver]; + + FIRCLSDemangleOperation *demangleOp = [[FIRCLSDemangleOperation alloc] init]; + [demangleOp setThreadArray:threadArray]; + + FIRCLSSerializeSymbolicatedFramesOperation *serializeOp = + [[FIRCLSSerializeSymbolicatedFramesOperation alloc] init]; + [serializeOp setThreadArray:threadArray]; + [serializeOp setOutputPath:[path stringByAppendingPathExtension:@"symbolicated"]]; + + [symbolicationOp start]; + [demangleOp start]; + [serializeOp start]; + + return YES; +} + +- (void)main { + if (![self.symbolResolver loadBinaryImagesFromFile:self.binaryImagePath]) { + return; + } + + [self.report enumerateSymbolicatableFilesInContent:^(NSString *path) { + [self symbolicateFile:path withResolver:self.symbolResolver]; + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h new file mode 100644 index 00000000..0680153a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h @@ -0,0 +1,24 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h" + +@interface FIRCLSDemangleOperation : FIRCLSThreadArrayOperation + ++ (NSString *)demangleSymbol:(const char *)symbol; ++ (NSString *)demangleCppSymbol:(const char *)symbol; + +- (NSString *)demangleSymbol:(const char *)symbol; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.mm b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.mm new file mode 100644 index 00000000..106a33cb --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.mm @@ -0,0 +1,96 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSDemangleOperation.h" +#include "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h" + +#import <cxxabi.h> + +@implementation FIRCLSDemangleOperation + ++ (NSString *)demangleSymbol:(const char *)symbol { + if (!symbol) { + return nil; + } + + if (strncmp(symbol, "_Z", 2) == 0) { + return [self demangleCppSymbol:symbol]; + } else if (strncmp(symbol, "__Z", 3) == 0) { + return [self demangleBlockInvokeCppSymbol:symbol]; + } + + return nil; +} + ++ (NSString *)demangleBlockInvokeCppSymbol:(const char *)symbol { + NSString *string = [NSString stringWithUTF8String:symbol]; + + // search backwards, because this string should be at the end + NSRange range = [string rangeOfString:@"_block_invoke" options:NSBackwardsSearch]; + + if (range.location == NSNotFound) { + return nil; + } + + // we need at least a "_Z..." for a valid C++ symbol, so make sure of that + if (range.location < 5) { + return nil; + } + + // extract the mangled C++ symbol from the string + NSString *cppSymbol = [string substringWithRange:NSMakeRange(1, range.location - 1)]; + cppSymbol = [self demangleSymbol:[cppSymbol UTF8String]]; + if (!cppSymbol) { + return nil; + } + + // extract out just the "_block_invoke..." part + string = + [string substringWithRange:NSMakeRange(range.location, [string length] - range.location)]; + + // and glue that onto the end + return [cppSymbol stringByAppendingString:string]; +} + ++ (NSString *)demangleCppSymbol:(const char *)symbol { + int status; + char *buffer = NULL; + + buffer = __cxxabiv1::__cxa_demangle(symbol, buffer, NULL, &status); + if (!buffer) { + return nil; + } + + NSString *result = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return result; +} + +- (NSString *)demangleSymbol:(const char *)symbol { + return [[self class] demangleSymbol:symbol]; +} + +- (void)main { + [self enumerateFramesWithBlock:^(FIRStackFrame *frame) { + NSString *demangedSymbol = [self demangleSymbol:[[frame rawSymbol] UTF8String]]; + + if (demangedSymbol) { + [frame setSymbol:demangedSymbol]; + } + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h new file mode 100644 index 00000000..7ce245db --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h @@ -0,0 +1,21 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h" + +@interface FIRCLSSerializeSymbolicatedFramesOperation : FIRCLSThreadArrayOperation + +@property(nonatomic, copy) NSString *outputPath; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.m new file mode 100644 index 00000000..445b37cb --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.m @@ -0,0 +1,63 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSerializeSymbolicatedFramesOperation.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSFile.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h" + +@implementation FIRCLSSerializeSymbolicatedFramesOperation + +- (void)main { + FIRCLSFile file; + + // Make sure not to open in append mode, so we can overwrite any pre-existing symbolication + // files. + if (!FIRCLSFileInitWithPathMode(&file, [self.outputPath fileSystemRepresentation], false, + false)) { + FIRCLSErrorLog(@"Failed to create output file"); + return; + } + + FIRCLSFileWriteSectionStart(&file, "threads"); + FIRCLSFileWriteArrayStart(&file); + + for (NSArray *frameArray in self.threadArray) { + FIRCLSFileWriteArrayStart(&file); + + for (FIRStackFrame *frame in frameArray) { + FIRCLSFileWriteHashStart(&file); + FIRCLSFileWriteHashEntryString(&file, "symbol", [[frame symbol] UTF8String]); + + // only include this field if it is present and different + if (![[frame rawSymbol] isEqualToString:[frame symbol]]) { + FIRCLSFileWriteHashEntryString(&file, "raw_symbol", [[frame rawSymbol] UTF8String]); + } + + FIRCLSFileWriteHashEntryUint64(&file, "offset", [frame offset]); + FIRCLSFileWriteHashEntryString(&file, "library", [[frame library] UTF8String]); + + FIRCLSFileWriteHashEnd(&file); + } + + FIRCLSFileWriteArrayEnd(&file); + } + + FIRCLSFileWriteArrayEnd(&file); + FIRCLSFileWriteSectionEnd(&file); + FIRCLSFileClose(&file); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h new file mode 100644 index 00000000..2a26d609 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h @@ -0,0 +1,23 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h" + +@class FIRCLSSymbolResolver; + +@interface FIRCLSSymbolicationOperation : FIRCLSThreadArrayOperation + +@property(nonatomic, strong) FIRCLSSymbolResolver *symbolResolver; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.m new file mode 100644 index 00000000..a8111fd1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.m @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSSymbolicationOperation.h" + +#import "Crashlytics/Crashlytics/Models/FIRCLSSymbolResolver.h" + +@implementation FIRCLSSymbolicationOperation + +- (void)main { + [self enumerateFramesWithBlock:^(FIRStackFrame *frame) { + [self.symbolResolver updateStackFrame:frame]; + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h new file mode 100644 index 00000000..0c2a1df5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h @@ -0,0 +1,25 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRStackFrame; + +@interface FIRCLSThreadArrayOperation : NSOperation + +@property(nonatomic, strong) NSArray *threadArray; + +- (void)enumerateFramesWithBlock:(void (^)(FIRStackFrame *frame))block; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.m new file mode 100644 index 00000000..76f59d95 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.m @@ -0,0 +1,31 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Operations/Symbolication/FIRCLSThreadArrayOperation.h" + +@implementation FIRCLSThreadArrayOperation + +- (void)enumerateFramesWithBlock:(void (^)(FIRStackFrame *frame))block { + for (NSArray *frameArray in self.threadArray) { + for (FIRStackFrame *frame in frameArray) { + block(frame); + + if ([self isCancelled]) { + break; + } + } + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h new file mode 100644 index 00000000..46384bb2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRExceptionModel_Private.h @@ -0,0 +1,33 @@ +// Copyright 2020 Google LLC +// +// 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. + +#ifndef FIRExceptionModel_Private_h +#define FIRExceptionModel_Private_h + +#import <Foundation/Foundation.h> + +#import "Crashlytics/Crashlytics/Public/FIRExceptionModel.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRExceptionModel (Private) + +@property(nonatomic, copy) NSString *name; +@property(nonatomic, copy) NSString *reason; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRExceptionModel_Private_h */ diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h new file mode 100644 index 00000000..9a02e65a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Private/FIRStackFrame_Private.h @@ -0,0 +1,44 @@ +// Copyright 2020 Google LLC +// +// 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. + +#import <Foundation/Foundation.h> + +#import "Crashlytics/Crashlytics/Public/FIRStackFrame.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is used in conjunction with recordExceptionModel to record information about + * non-ObjC/C++ exceptions. All information included here will be displayed in the Crashlytics UI, + * and can influence crash grouping. Be particularly careful with the use of the address property. + *If set, Crashlytics will attempt symbolication and could overwrite other properities in the + *process. + **/ +@interface FIRStackFrame (Private) + ++ (instancetype)stackFrame; ++ (instancetype)stackFrameWithAddress:(NSUInteger)address; ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol; + +@property(nonatomic, copy, nullable) NSString *symbol; +@property(nonatomic, copy, nullable) NSString *rawSymbol; +@property(nonatomic, copy, nullable) NSString *library; +@property(nonatomic, copy, nullable) NSString *fileName; +@property(nonatomic, assign) uint32_t lineNumber; +@property(nonatomic, assign) uint64_t offset; +@property(nonatomic, assign) uint64_t address; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h new file mode 100644 index 00000000..9f651537 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRCrashlytics.h @@ -0,0 +1,192 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#import "FIRExceptionModel.h" + +#if __has_include(<Crashlytics/Crashlytics.h>) +#warning "FirebaseCrashlytics and Crashlytics are not compatible \ +in the same app because including multiple crash reporters can \ +cause problems when registering exception handlers." +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase Crashlytics API provides methods to annotate and manage fatal and + * non-fatal reports captured and reported to Firebase Crashlytics. + * + * By default, Firebase Crashlytics is initialized with `[FIRApp configure]`. + * + * Note: The Crashlytics class cannot be subclassed. If this makes testing difficult, + * we suggest using a wrapper class or a protocol extension. + */ +NS_SWIFT_NAME(Crashlytics) +@interface FIRCrashlytics : NSObject + +/** :nodoc: */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Accesses the singleton Crashlytics instance. + * + * @return The singleton Crashlytics instance. + */ ++ (instancetype)crashlytics NS_SWIFT_NAME(crashlytics()); + +/** + * Adds logging that is sent with your crash data. The logging does not appear in the + * system.log and is only visible in the Crashlytics dashboard. + * + * @param msg Message to log + */ +- (void)log:(NSString *)msg; + +/** + * Adds logging that is sent with your crash data. The logging does not appear in the + * system.log and is only visible in the Crashlytics dashboard. + * + * @param format Format of string + * @param ... A comma-separated list of arguments to substitute into format + */ +- (void)logWithFormat:(NSString *)format, ... NS_FORMAT_FUNCTION(1, 2); + +/** + * Adds logging that is sent with your crash data. The logging does not appear in the + * system.log and is only visible in the Crashlytics dashboard. + * + * @param format Format of string + * @param args Arguments to substitute into format + */ +- (void)logWithFormat:(NSString *)format + arguments:(va_list)args NS_SWIFT_NAME(log(format:arguments:)); + +/** + * Sets a custom key and value to be associated with subsequent fatal and non-fatal reports. + * When setting an object value, the object is converted to a string. This is + * typically done by calling "-[NSObject description]". + * + * @param value The value to be associated with the key + * @param key A unique key + */ +- (void)setCustomValue:(id)value forKey:(NSString *)key; + +/** + * Records a user ID (identifier) that's associated with subsequent fatal and non-fatal reports. + * + * If you want to associate a crash with a specific user, we recommend specifying an arbitrary + * string (e.g., a database, ID, hash, or other value that you can index and query, but is + * meaningless to a third-party observer). This allows you to facilitate responses for support + * requests and reach out to users for more information. + * + * @param userID An arbitrary user identifier string that associates a user to a record in your + * system. + */ +- (void)setUserID:(NSString *)userID; + +/** + * Records a non-fatal event described by an NSError object. The events are + * grouped and displayed similarly to crashes. Keep in mind that this method can be expensive. + * The total number of NSErrors that can be recorded during your app's life-cycle is limited by a + * fixed-size circular buffer. If the buffer is overrun, the oldest data is dropped. Errors are + * relayed to Crashlytics on a subsequent launch of your application. + * + * @param error Non-fatal error to be recorded + */ +- (void)recordError:(NSError *)error NS_SWIFT_NAME(record(error:)); + +/** + * Records an Exception Model described by an FIRExceptionModel object. The events are + * grouped and displayed similarly to crashes. Keep in mind that this method can be expensive. + * The total number of FIRExceptionModels that can be recorded during your app's life-cycle is + * limited by a fixed-size circular buffer. If the buffer is overrun, the oldest data is dropped. + * Exception Models are relayed to Crashlytics on a subsequent launch of your application. + * + * @param exceptionModel Instance of the FIRExceptionModel to be recorded + */ +- (void)recordExceptionModel:(FIRExceptionModel *)exceptionModel + NS_SWIFT_NAME(record(exceptionModel:)); + +/** + * Returns whether the app crashed during the previous execution. + */ +- (BOOL)didCrashDuringPreviousExecution; + +/** + * Enables/disables automatic data collection. + * + * Calling this method overrides both the FirebaseCrashlyticsCollectionEnabled flag in your + * App's Info.plist and FIRApp's isDataCollectionDefaultEnabled flag. + * + * When you set a value for this method, it persists across runs of the app. + * + * The value does not apply until the next run of the app. If you want to disable data + * collection without rebooting, add the FirebaseCrashlyticsCollectionEnabled flag to your app's + * Info.plist. + * * + * @param enabled Determines whether automatic data collection is enabled + */ +- (void)setCrashlyticsCollectionEnabled:(BOOL)enabled; + +/** + * Indicates whether or not automatic data collection is enabled + * + * This method uses three ways to decide whether automatic data collection is enabled, + * in order of priority: + * - If setCrashlyticsCollectionEnabled iscalled with a value, use it + * - If the FirebaseCrashlyticsCollectionEnabled key is in your app's Info.plist, use it + * - Otherwise, use the default isDataCollectionDefaultEnabled in FIRApp + */ +- (BOOL)isCrashlyticsCollectionEnabled; + +/** + * Determines whether there are any unsent crash reports cached on the device, then calls the given + * callback. + * + * The callback only executes if automatic data collection is disabled. You can use + * the callback to get one-time consent from a user upon a crash, and then call + * sendUnsentReports or deleteUnsentReports, depending on whether or not the user gives consent. + * + * Disable automatic collection by: + * - Adding the FirebaseCrashlyticsCollectionEnabled: NO key to your App's Info.plist + * - Calling [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:NO] in your app + * - Setting FIRApp's isDataCollectionDefaultEnabled to NO + * + * @param completion The callback that's executed once Crashlytics finishes checking for unsent + * reports. The callback is set to YES if there are unsent reports on disk. + */ +- (void)checkForUnsentReportsWithCompletion:(void (^)(BOOL))completion + NS_SWIFT_NAME(checkForUnsentReports(completion:)); + +/** + * Enqueues any unsent reports on the device to upload to Crashlytics. + * + * This method only applies if automatic data collection is disabled. + * + * When automatic data collection is enabled, Crashlytics automatically uploads and deletes reports + * at startup, so this method is ignored. + */ +- (void)sendUnsentReports; + +/** + * Deletes any unsent reports on the device. + * + * This method only applies if automatic data collection is disabled. + */ +- (void)deleteUnsentReports; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h new file mode 100644 index 00000000..5458dcc1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRExceptionModel.h @@ -0,0 +1,57 @@ +// Copyright 2020 Google LLC +// +// 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. + +#import <Foundation/Foundation.h> + +#import "FIRStackFrame.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase Crashlytics Exception Model provides a way to report custom exceptions + * to Crashlytics that came from a runtime environment outside of the native + * platform Crashlytics is running in. + */ +NS_SWIFT_NAME(ExceptionModel) +@interface FIRExceptionModel : NSObject + +/** :nodoc: */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes an Exception Model model with the given required fields. + * + * @param name - typically the type of the Exception class + * @param reason - the human-readable reason the issue occurred + */ +- (instancetype)initWithName:(NSString *)name reason:(NSString *)reason; + +/** + * Creates an Exception Model model with the given required fields. + * + * @param name - typically the type of the Exception class + * @param reason - the human-readable reason the issue occurred + */ ++ (instancetype)exceptionModelWithName:(NSString *)name + reason:(NSString *)reason NS_SWIFT_UNAVAILABLE(""); + +/** + * A list of Stack Frames that make up the stack trace. The order of the stack trace is top-first, + * so typically the "main" function is the last element in this list. + */ +@property(nonatomic, copy) NSArray<FIRStackFrame *> *stackTrace; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h new file mode 100644 index 00000000..f2f5d966 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FIRStackFrame.h @@ -0,0 +1,53 @@ +// Copyright 2020 Google LLC +// +// 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. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase Crashlytics Stack Frame provides a way to construct the lines of + * a stack trace for reporting along with a recorded Exception Model. + */ +NS_SWIFT_NAME(StackFrame) +@interface FIRStackFrame : NSObject + +/** :nodoc: */ +- (instancetype)init NS_UNAVAILABLE; + +/** + * Initializes a symbolicated Stack Frame with the given required fields. Symbolicated + * Stack Frames will appear in the Crashlytics dashboard as reported in these fields. + * + * @param symbol - The function or method name + * @param file - the file where the exception occurred + * @param line - the line number + */ +- (instancetype)initWithSymbol:(NSString *)symbol file:(NSString *)file line:(NSInteger)line; + +/** + * Creates a symbolicated Stack Frame with the given required fields. Symbolicated + * Stack Frames will appear in the Crashlytics dashboard as reported in these fields. * + * + * @param symbol - The function or method name + * @param file - the file where the exception occurred + * @param line - the line number + */ ++ (instancetype)stackFrameWithSymbol:(NSString *)symbol + file:(NSString *)file + line:(NSInteger)line NS_SWIFT_UNAVAILABLE(""); + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h new file mode 100644 index 00000000..9022811b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Public/FirebaseCrashlytics.h @@ -0,0 +1,19 @@ +/* + * Copyright 2019 Google + * + * 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. + */ + +#import "FIRCrashlytics.h" +#import "FIRExceptionModel.h" +#import "FIRStackFrame.h" diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h new file mode 100644 index 00000000..2708d095 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h @@ -0,0 +1,59 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#if __has_include(<FBLPromises/FBLPromises.h>) +#import <FBLPromises/FBLPromises.h> +#else +#import "FBLPromises.h" +#endif + +@class FIRCLSApplicationIdentifierModel; +@class FIRCLSDataCollectionToken; +@class FIRCLSFileManager; +@class FIRCLSInstallIdentifierModel; +@class FIRCLSSettings; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Use this class to retrieve remote settings for the application from crashlytics backend, and + * onboard the application on the server. + */ +@interface FIRCLSSettingsOnboardingManager : NSObject + +/** + * Designated Initializer. + */ +- (instancetype)initWithAppIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + settings:(FIRCLSSettings *)settings + fileManager:(FIRCLSFileManager *)fileManager + googleAppID:(NSString *)googleAppID NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * This method kicks off downloading settings and onboarding for the app. + * @param googleAppID (required) GMP id for the app. + * @param token (required) Data collection token signifying we can make network calls + */ +- (void)beginSettingsAndOnboardingWithGoogleAppId:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token + waitForCompletion:(BOOL)waitForCompletion; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.m new file mode 100644 index 00000000..68492213 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.m @@ -0,0 +1,243 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Settings/FIRCLSSettingsOnboardingManager.h" + +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSFileManager.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" +#import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h" +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h" +#import "Crashlytics/Shared/FIRCLSConstants.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h" + +@interface FIRCLSSettingsOnboardingManager () <FIRCLSDownloadAndSaveSettingsOperationDelegate, + FIRCLSOnboardingOperationDelegate> + +@property(nonatomic, strong) FIRCLSApplicationIdentifierModel *appIDModel; +@property(nonatomic, strong) FIRCLSInstallIdentifierModel *installIDModel; + +@property(nonatomic, strong) FIRCLSSettings *settings; + +@property(nonatomic, nullable, strong) FIRCLSOnboardingOperation *onboardingOperation; +@property(nonatomic, strong) FIRCLSFileManager *fileManager; + +// set to YES once onboarding call has been made. +@property(nonatomic) BOOL hasAttemptedAppConfigure; + +@property(nonatomic) NSDictionary *configuration; +@property(nonatomic) NSDictionary *defaultConfiguration; +@property(nonatomic, copy) NSString *googleAppID; +@property(nonatomic, copy) NSDictionary *kitVersionsByKitBundleIdentifier; +@property(nonatomic, readonly) FIRCLSFABNetworkClient *networkClient; + +@end + +@implementation FIRCLSSettingsOnboardingManager + +- (instancetype)initWithAppIDModel:(FIRCLSApplicationIdentifierModel *)appIDModel + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + settings:(FIRCLSSettings *)settings + fileManager:(FIRCLSFileManager *)fileManager + googleAppID:(NSString *)googleAppID { + self = [super init]; + if (!self) { + return nil; + } + + _appIDModel = appIDModel; + _installIDModel = installIDModel; + _settings = settings; + _fileManager = fileManager; + _googleAppID = googleAppID; + + _networkClient = [[FIRCLSFABNetworkClient alloc] initWithQueue:nil]; + + return self; +} + +- (void)beginSettingsAndOnboardingWithGoogleAppId:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token + waitForCompletion:(BOOL)waitForCompletion { + NSParameterAssert(googleAppID); + + self.googleAppID = googleAppID; + + // This map helps us determine what versions of the SDK + // are out there. We're keeping the Fabric value in there for + // backwards compatibility + // TODO(b/141747635) + self.kitVersionsByKitBundleIdentifier = @{ + FIRCLSApplicationGetSDKBundleID() : @CLS_SDK_DISPLAY_VERSION, + }; + + [self beginSettingsDownload:token waitForCompletion:waitForCompletion]; +} + +#pragma mark Helper methods + +/** + * Makes a settings download request. If the request fails, the error is handled silently(with a log + * statement). If the server response indicates onboarding is needed, an onboarding request is sent + * to the server. If the onboarding request fails, the error is handled silently(with a log + * statement). + */ +- (void)beginSettingsDownload:(FIRCLSDataCollectionToken *)token + waitForCompletion:(BOOL)waitForCompletion { + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + + FIRCLSDownloadAndSaveSettingsOperation *operation = nil; + operation = [[FIRCLSDownloadAndSaveSettingsOperation alloc] + initWithGoogleAppID:self.googleAppID + delegate:self + settingsURL:self.settingsURL + settingsDirectoryPath:self.fileManager.settingsDirectoryPath + settingsFilePath:self.fileManager.settingsFilePath + installIDModel:self.installIDModel + networkClient:self.networkClient + token:token]; + + if (waitForCompletion) { + operation.asyncCompletion = ^(NSError *error) { + dispatch_semaphore_signal(semaphore); + }; + } + + [operation startWithToken:token]; + + if (waitForCompletion) { + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + } +} + +- (void)beginOnboarding:(BOOL)appCreate + endpointString:(NSString *)endpoint + token:(FIRCLSDataCollectionToken *)token { + [self.onboardingOperation cancel]; + + self.onboardingOperation = + [[FIRCLSOnboardingOperation alloc] initWithDelegate:self + shouldCreate:appCreate + googleAppID:self.googleAppID + kitVersionsByKitBundleIdentifier:self.kitVersionsByKitBundleIdentifier + appIdentifierModel:self.appIDModel + endpointString:endpoint + networkClient:self.networkClient + token:token + settings:self.settings]; + + [self.onboardingOperation startWithToken:token]; +} + +- (void)finishNetworkingSession { + [self.networkClient invalidateAndCancel]; +} + +#pragma mark FIRCLSOnboardingOperationDelegate methods + +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppCreationWithError:(nullable NSError *)error { + if (error) { + FIRCLSErrorLog(@"Unable to complete application configure: %@", error); + [self finishNetworkingSession]; + return; + } + self.onboardingOperation = nil; + FIRCLSDebugLog(@"Completed configure"); + + // now, go get settings, as they can change (and it completes the onboarding process) + [self beginSettingsDownload:operation.token waitForCompletion:NO]; +} + +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppUpdateWithError:(nullable NSError *)error { + [self finishNetworkingSession]; + if (error) { + FIRCLSErrorLog(@"Unable to complete application update: %@", error); + return; + } + self.onboardingOperation = nil; + FIRCLSDebugLog(@"Completed application update"); +} + +#pragma mark FIRCLSDownloadAndSaveSettingsOperationDelegate methods + +- (void)operation:(FIRCLSDownloadAndSaveSettingsOperation *)operation + didDownloadAndSaveSettingsWithError:(nullable NSError *)error { + if (error) { + FIRCLSErrorLog(@"Failed to download settings %@", error); + [self finishNetworkingSession]; + return; + } + + FIRCLSDebugLog(@"Settings downloaded successfully"); + + NSTimeInterval currentTimestamp = [NSDate timeIntervalSinceReferenceDate]; + [self.settings cacheSettingsWithGoogleAppID:self.googleAppID currentTimestamp:currentTimestamp]; + + // only try this once + if (self.hasAttemptedAppConfigure) { + FIRCLSDebugLog(@"App already onboarded in this run of the app"); + [self finishNetworkingSession]; + return; + } + + // Onboarding is still needed in Firebase, here are the backend app states - + // 1. When the app is created in the Firebase console, app state: built (client settings call + // returns app status: new) + // 2. After onboarding call is made, app state: build_configured + // 3. Another settings call is triggered after onboarding, app state: activated + if ([self.settings appNeedsOnboarding]) { + FIRCLSDebugLog(@"Starting onboarding with app create"); + self.hasAttemptedAppConfigure = YES; + [self beginOnboarding:YES endpointString:FIRCLSConfigureEndpoint token:operation.token]; + return; + } + + if ([self.settings appUpdateRequired]) { + FIRCLSDebugLog(@"Starting onboarding with app update"); + self.hasAttemptedAppConfigure = YES; + [self beginOnboarding:NO endpointString:FIRCLSConfigureEndpoint token:operation.token]; + return; + } + + // we're all set! + [self finishNetworkingSession]; +} + +- (NSURL *)settingsURL { + // GET + // /spi/v2/platforms/:platform/apps/:identifier/settings?build_version=1234&display_version=abc&instance=xyz&source=1 + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:FIRCLSSettingsEndpoint]; + + [url appendComponent:@"/spi/v2/platforms/"]; + [url escapeAndAppendComponent:self.appIDModel.platform]; + [url appendComponent:@"/gmp/"]; + [url escapeAndAppendComponent:self.googleAppID]; + [url appendComponent:@"/settings"]; + + [url appendValue:self.appIDModel.buildVersion forQueryParam:@"build_version"]; + [url appendValue:self.appIDModel.displayVersion forQueryParam:@"display_version"]; + [url appendValue:self.appIDModel.buildInstanceID forQueryParam:@"instance"]; + [url appendValue:@(self.appIDModel.installSource) forQueryParam:@"source"]; + // TODO: find the right param name for KitVersions and add them here + return url.URL; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h new file mode 100644 index 00000000..7b40ec73 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h @@ -0,0 +1,71 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * This class is a model for identifiers related to the application binary. + * It is thread-safe. + */ +@interface FIRCLSApplicationIdentifierModel : NSObject + +@property(nonatomic, readonly, nullable) NSString* bundleID; + +/** + * Returns the user-facing app name + */ +@property(nonatomic, readonly, nullable) NSString* displayName; + +@property(nonatomic, readonly, nullable) NSString* platform; +@property(nonatomic, readonly, nullable) NSString* buildVersion; +@property(nonatomic, readonly, nullable) NSString* displayVersion; + +/** + * Returns the synthesized app version, similar to how the backend does it + * <displayVersion> (<buildVersion>) + */ +@property(nonatomic, readonly, nullable) NSString* synthesizedVersion; + +@property(nonatomic, readonly) FIRCLSApplicationInstallationSourceType installSource; + +/** + * A mapping between all supported architectures and their UUIDs + */ +@property(nonatomic, readonly) NSDictionary* architectureUUIDMap; + +/** + * Returns the linked OS SDK + */ +@property(nonatomic, readonly) NSString* builtSDKString; + +/** + * Returns the min supported OS + */ +@property(nonatomic, readonly) NSString* minimumSDKString; + +/** + * The unique identifier for this instance of the version of app running Crashlytics. This is + * computed by hashing the app itself. + * + * On Android, this is called the Build ID + */ +@property(nonatomic, readonly) NSString* buildInstanceID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.m new file mode 100644 index 00000000..59fafef0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.m @@ -0,0 +1,138 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" +#import "Crashlytics/Shared/FIRCLSUUID.h" + +@interface FIRCLSApplicationIdentifierModel () + +@property(nonatomic, copy, readwrite) NSDictionary *architectureUUIDMap; +@property(nonatomic, copy, readwrite) NSString *buildInstanceID; +@property(nonatomic, readonly) FIRCLSMachOVersion builtSDK; +@property(nonatomic, readonly) FIRCLSMachOVersion minimumSDK; + +@end + +@implementation FIRCLSApplicationIdentifierModel + +- (nullable instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + if (![self computeExecutableInfo]) { + return nil; + } + + [self computeInstanceIdentifier]; + + return self; +} + +- (NSString *)bundleID { + return FIRCLSApplicationGetBundleIdentifier(); +} + +- (NSString *)displayName { + return FIRCLSApplicationGetName(); +} + +- (NSString *)platform { + return FIRCLSApplicationGetPlatform(); +} + +- (NSString *)buildVersion { + return FIRCLSApplicationGetBundleVersion(); +} + +- (NSString *)displayVersion { + return FIRCLSApplicationGetShortBundleVersion(); +} + +- (NSString *)synthesizedVersion { + return [NSString stringWithFormat:@"%@ (%@)", self.displayVersion, self.buildVersion]; +} + +- (FIRCLSApplicationInstallationSourceType)installSource { + return FIRCLSApplicationInstallationSource(); +} + +- (NSString *)builtSDKString { + return FIRCLSMachOFormatVersion(&_builtSDK); +} + +- (NSString *)minimumSDKString { + return FIRCLSMachOFormatVersion(&_minimumSDK); +} + +- (BOOL)computeExecutableInfo { + struct FIRCLSMachOFile file; + + if (!FIRCLSMachOFileInitWithCurrent(&file)) { + return NO; + } + + NSMutableDictionary *executables = [NSMutableDictionary dictionary]; + + FIRCLSMachOFileEnumerateSlices(&file, ^(FIRCLSMachOSliceRef fileSlice) { + NSString *arch; + + arch = [NSString stringWithUTF8String:FIRCLSMachOSliceGetArchitectureName(fileSlice)]; + + FIRCLSMachOSliceEnumerateLoadCommands( + fileSlice, ^(uint32_t type, uint32_t size, const struct load_command *cmd) { + if (type == LC_UUID) { + const uint8_t *uuid; + + uuid = FIRCLSMachOGetUUID(cmd); + + [executables setObject:FIRCLSUUIDToNSString(uuid) forKey:arch]; + } else if (type == LC_VERSION_MIN_MACOSX || type == LC_VERSION_MIN_IPHONEOS) { + self->_minimumSDK = FIRCLSMachOGetMinimumOSVersion(cmd); + self->_builtSDK = FIRCLSMachOGetLinkedSDKVersion(cmd); + } + }); + }); + + FIRCLSMachOFileDestroy(&file); + + _architectureUUIDMap = executables; + + return YES; +} + +- (void)computeInstanceIdentifier { + // build up the components of the instance identifier + NSMutableString *string = [NSMutableString string]; + + // first, the uuids, sorted by architecture name + for (NSString *key in + [[_architectureUUIDMap allKeys] sortedArrayUsingSelector:@selector(compare:)]) { + [string appendString:[self.architectureUUIDMap objectForKey:key]]; + } + + // TODO: the instance identifier calculation needs to match Beta's expectation. So, we have to + // continue generating a less-correct value for now. One day, we should encorporate a hash of the + // Info.plist and icon data. + + _buildInstanceID = FIRCLSHashNSData([string dataUsingEncoding:NSUTF8StringEncoding]); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h new file mode 100644 index 00000000..af14e465 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h @@ -0,0 +1,80 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h" + +@class FIRCLSDownloadAndSaveSettingsOperation; +@class FIRCLSFABNetworkClient; +@class FIRCLSInstallIdentifierModel; + +NS_ASSUME_NONNULL_BEGIN + +/** + * This is the protocol that a delegate of FIRCLSDownloadAndSaveSettingsOperation needs to follow. + */ +@protocol FIRCLSDownloadAndSaveSettingsOperationDelegate <NSObject> + +@required + +/** + * Method that is called when settings have been downloaded and saved, or an error has occurred + * during the operation. This method may be called on an arbitrary background thread. + */ +- (void)operation:(FIRCLSDownloadAndSaveSettingsOperation *)operation + didDownloadAndSaveSettingsWithError:(nullable NSError *)error; + +@end + +/** + * This operation downloads settings from the backend servers, and saves them in file on disk. + */ +@interface FIRCLSDownloadAndSaveSettingsOperation : FIRCLSNetworkOperation + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token NS_UNAVAILABLE; + +/** + * @param googleAppID must NOT be nil + * @param delegate gets a callback after settings have been downloaded or an error occurs. + * @param settingsURL must NOT be nil. This is the URL to which a download request is made. + * @param settingsDirectoryPath must NOT be nil. This is the directory on disk where the settings + * are persisted. + * @param settingsFilePath must NOT be nil. It is the full file path(including file name) in which + * settings will be persisted on disk. + * @param installIDModel must NOT be nil. This value is sent back to the backend to uniquely + * identify the app install. + */ +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + delegate:(id<FIRCLSDownloadAndSaveSettingsOperationDelegate>)delegate + settingsURL:(NSURL *)settingsURL + settingsDirectoryPath:(NSString *)settingsDirectoryPath + settingsFilePath:(NSString *)settingsFilePath + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token NS_DESIGNATED_INITIALIZER; + +/** + * Delegate of this operation. + */ +@property(nonatomic, readonly, weak) id<FIRCLSDownloadAndSaveSettingsOperationDelegate> delegate; + +/** + * When an error occurs during this operation, it is made available in this property. + */ +@property(nonatomic, readonly) NSError *error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.m new file mode 100644 index 00000000..75eb70c0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.m @@ -0,0 +1,132 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSDownloadAndSaveSettingsOperation.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSInstallIdentifierModel.h" +#import "Crashlytics/Shared/FIRCLSConstants.h" +#import "Crashlytics/Shared/FIRCLSFABHost.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h" + +@interface FIRCLSDownloadAndSaveSettingsOperation () + +/** + * Method called to fetch the URL from where settings have to be downloaded. + */ +@property(readonly, nonatomic) NSURL *settingsURL; +/** + * File manager which will be used to save settings on disk. + */ +@property(readonly, nonatomic) NSFileManager *fileManager; + +/** + * Directory path on which settings file will be saved + */ +@property(readonly, nonatomic) NSString *settingsDirectoryPath; +/** + * Complete file path on which settings file will be saved + */ +@property(readonly, nonatomic) NSString *settingsFilePath; +/** + * App install identifier. + */ +@property(strong, readonly, nonatomic) FIRCLSInstallIdentifierModel *installIDModel; + +@property(weak, readonly, nonatomic) FIRCLSFABNetworkClient *networkClient; + +@end + +@implementation FIRCLSDownloadAndSaveSettingsOperation + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + delegate:(id<FIRCLSDownloadAndSaveSettingsOperationDelegate>)delegate + settingsURL:(NSURL *)settingsURL + settingsDirectoryPath:(NSString *)settingsDirectoryPath + settingsFilePath:(NSString *)settingsFilePath + installIDModel:(FIRCLSInstallIdentifierModel *)installIDModel + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token { + NSParameterAssert(settingsURL); + NSParameterAssert(settingsDirectoryPath); + NSParameterAssert(settingsFilePath); + NSParameterAssert(installIDModel); + + self = [super initWithGoogleAppID:googleAppID token:token]; + if (self) { + _delegate = delegate; + _settingsURL = settingsURL.copy; + _settingsDirectoryPath = settingsDirectoryPath.copy; + _settingsFilePath = settingsFilePath.copy; + _fileManager = [[NSFileManager alloc] init]; + _installIDModel = installIDModel; + _networkClient = networkClient; + } + return self; +} + +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:(NSURL *)url { + NSMutableURLRequest *request = + [super mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:url]; + request.HTTPMethod = @"GET"; + [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; + [request setValue:self.installIDModel.installID + forHTTPHeaderField:@"X-Crashlytics-Installation-ID"]; + [request setValue:FIRCLSHostModelInfo() forHTTPHeaderField:@"X-Crashlytics-Device-Model"]; + [request setValue:FIRCLSHostOSBuildVersion() + forHTTPHeaderField:@"X-Crashlytics-OS-Build-Version"]; + [request setValue:FIRCLSHostOSDisplayVersion() + forHTTPHeaderField:@"X-Crashlytics-OS-Display-Version"]; + [request setValue:FIRCLSVersion forHTTPHeaderField:@"X-Crashlytics-API-Client-Version"]; + + return request; +} + +- (void)main { + NSMutableURLRequest *request = + [self mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:self.settingsURL]; + + [self.networkClient + startDownloadTaskWithRequest:request + retryLimit:1 + completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { + if (error) { + self->_error = error; + [self.delegate operation:self didDownloadAndSaveSettingsWithError:self.error]; + [self finishWithError:error]; + return; + } + // This move needs to happen synchronously, because after this method completes, + // the file will not be available. + NSError *moveError = nil; + + // this removal will frequently fail, and we don't want the warning + [self.fileManager removeItemAtPath:self.settingsDirectoryPath error:nil]; + + [self.fileManager createDirectoryAtPath:self.settingsDirectoryPath + withIntermediateDirectories:YES + attributes:nil + error:nil]; + if (![self.fileManager moveItemAtPath:location.path + toPath:self.settingsFilePath + error:&moveError]) { + FIRCLSErrorLog(@"Unable to complete settings download %@", moveError); + self->_error = moveError; + } + [self.delegate operation:self didDownloadAndSaveSettingsWithError:self.error]; + [self finishWithError:self.error]; + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h new file mode 100644 index 00000000..405f6edf --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h @@ -0,0 +1,55 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +@class FIRCLSDataCollectionToken; +@class FIRCLSSettings; + +/** + * This is a base class for network based operations. + */ +@interface FIRCLSNetworkOperation : FIRCLSFABAsyncOperation + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/** + * Designated initializer. All parameters are mandatory and must not be nil. + */ +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token NS_DESIGNATED_INITIALIZER; + +- (void)start NS_UNAVAILABLE; +- (void)startWithToken:(FIRCLSDataCollectionToken *)token; + +/** + * Creates a mutable request for posting to Crashlytics backend with a default timeout. + */ +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:(NSURL *)url; + +/** + * Creates a mutable request for posting to Crashlytics backend with given timeout. + */ +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeadersForURL:(NSURL *)url + timeout:(NSTimeInterval)timeout; + +@property(nonatomic, strong, readonly) FIRCLSDataCollectionToken *token; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.m new file mode 100644 index 00000000..8c857ff2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.m @@ -0,0 +1,92 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h" + +#import "Crashlytics/Crashlytics/Components/FIRCLSApplication.h" +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Shared/FIRCLSConstants.h" + +@interface FIRCLSNetworkOperation () + +@property(nonatomic, strong, readonly) NSString *googleAppID; + +@end + +@implementation FIRCLSNetworkOperation + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token { + NSParameterAssert(googleAppID); + if (!googleAppID) { + return nil; + } + + self = [super init]; + if (self) { + _googleAppID = googleAppID; + _token = token; + } + return self; +} + +- (void)startWithToken:(FIRCLSDataCollectionToken *)token { + // Settings and Onboarding are considered data collection, so we must only + // call this with a valid token + if (![token isValid]) { + FIRCLSErrorLog(@"Skipping network operation with invalid data collection token"); + return; + } + + [super start]; +} + +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeaderFieldsAndTimeoutForURL:(NSURL *)url { + return [self mutableRequestWithDefaultHTTPHeadersForURL:url timeout:10.0]; +} + +- (NSMutableURLRequest *)mutableRequestWithDefaultHTTPHeadersForURL:(NSURL *)url + timeout:(NSTimeInterval)timeout { + NSMutableURLRequest *request = + [NSMutableURLRequest requestWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:timeout]; + + NSString *localeId = self.localeIdentifier; + + [request setValue:self.userAgentString forHTTPHeaderField:FIRCLSNetworkUserAgent]; + [request setValue:FIRCLSNetworkUTF8 forHTTPHeaderField:FIRCLSNetworkAcceptCharset]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkAcceptLanguage]; + [request setValue:localeId forHTTPHeaderField:FIRCLSNetworkContentLanguage]; + [request setValue:FIRCLSDeveloperToken forHTTPHeaderField:FIRCLSNetworkCrashlyticsDeveloperToken]; + [request setValue:FIRCLSApplicationGetSDKBundleID() + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientId]; + [request setValue:FIRCLSVersion + forHTTPHeaderField:FIRCLSNetworkCrashlyticsAPIClientDisplayVersion]; + [request setValue:self.googleAppID forHTTPHeaderField:FIRCLSNetworkCrashlyticsGoogleAppId]; + + return request; +} + +- (NSString *)userAgentString { + return [NSString stringWithFormat:@"%@/%@", FIRCLSApplicationGetSDKBundleID(), FIRCLSVersion]; +} + +- (NSString *)localeIdentifier { + return NSLocale.currentLocale.localeIdentifier; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h new file mode 100644 index 00000000..2ad915a1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h @@ -0,0 +1,84 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Crashlytics/DataCollection/FIRCLSDataCollectionToken.h" +#import "Crashlytics/Crashlytics/Settings/Models/FIRCLSApplicationIdentifierModel.h" +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSNetworkOperation.h" + +NS_ASSUME_NONNULL_BEGIN + +extern NSString *const FIRCLSOnboardingErrorDomain; + +@class FIRCLSOnboardingOperation; +@class FIRCLSFABNetworkClient; +@class FIRCLSSettings; + +/** + * This is the protocol that a delegate of FIRCLSOnboardingOperation should follow. + */ +@protocol FIRCLSOnboardingOperationDelegate <NSObject> +@required + +/** + * This callback is for the delegate to know that app update has completed with/without an error. + */ +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppUpdateWithError:(nullable NSError *)error; +/** + * This callback is for the delegate to know that app creation has completed with/without an error. + */ +- (void)onboardingOperation:(FIRCLSOnboardingOperation *)operation + didCompleteAppCreationWithError:(nullable NSError *)error; + +@end + +/** + * This class onboards the app, by making request to the backend servers. + */ +@interface FIRCLSOnboardingOperation : FIRCLSNetworkOperation + +/** + * When an error occurs during this operation, it is made available in this property. + */ +@property(nonatomic, readonly) NSError *error; + +- (instancetype)initWithGoogleAppID:(NSString *)googleAppID + token:(FIRCLSDataCollectionToken *)token NS_UNAVAILABLE; + +/** + * Designated initializer. + * @param delegate may be nil. Gets callbacks when app creation or updation succeeds or gets errored + * out. + * @param googleAppID must NOT be nil. + * @param kitVersionsByKitBundleIdentifier may be nil. Maps Kit bundle identifier to kit version + * being used in the app. + * @param appIdentifierModel must NOT be nil. Used to get information required in the onboarding + * network call. + * @param appEndPoint must NOT be nil. Endpoint which needs to be hit with the onboarding request. + * @param settings which are used to fetch the organization identifier. + */ +- (instancetype)initWithDelegate:(id<FIRCLSOnboardingOperationDelegate>)delegate + shouldCreate:(BOOL)shouldCreate + googleAppID:(NSString *)googleAppID + kitVersionsByKitBundleIdentifier:(NSDictionary *)kitVersionsByKitBundleIdentifier + appIdentifierModel:(FIRCLSApplicationIdentifierModel *)appIdentifierModel + endpointString:(NSString *)appEndPoint + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token + settings:(FIRCLSSettings *)settings NS_DESIGNATED_INITIALIZER; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.m new file mode 100644 index 00000000..17b3fec3 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.m @@ -0,0 +1,208 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Crashlytics/Settings/Operations/FIRCLSOnboardingOperation.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Crashlytics/Models/FIRCLSSettings.h" +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSConstants.h" +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h" +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h" + +// The SPIv1/v2 onboarding flow looks something like this: +// - get settings +// - settings says we're good, nothing to do +// - settings says update +// - do an update +// - settings says new +// - do a create +// - get settings again (and do *not* take action after that) + +NSString *const FIRCLSOnboardingErrorDomain = @"FIRCLSOnboardingErrorDomain"; + +typedef NS_ENUM(NSInteger, FIRCLSOnboardingError) { + FIRCLSOnboardingErrorMultipartMimeConfiguration +}; + +@interface FIRCLSOnboardingOperation () + +@property(nonatomic) BOOL shouldCreate; +@property(nonatomic, readonly) FIRCLSApplicationIdentifierModel *appIdentifierModel; +@property(nonatomic, readonly) NSString *appEndpoint; +@property(nonatomic, readonly, unsafe_unretained) id<FIRCLSOnboardingOperationDelegate> delegate; +@property(nonatomic, weak, readonly) FIRCLSFABNetworkClient *networkClient; +@property(nonatomic, readonly) NSDictionary *kitVersionsByKitBundleIdentifier; +@property(nonatomic, readonly) FIRCLSSettings *settings; +@end + +@implementation FIRCLSOnboardingOperation + +#pragma mark lifecycle methods + +- (instancetype)initWithDelegate:(id<FIRCLSOnboardingOperationDelegate>)delegate + shouldCreate:(BOOL)shouldCreate + googleAppID:(NSString *)googleAppID + kitVersionsByKitBundleIdentifier:(NSDictionary *)kitVersionsByKitBundleIdentifier + appIdentifierModel:(FIRCLSApplicationIdentifierModel *)appIdentifierModel + endpointString:(NSString *)appEndPoint + networkClient:(FIRCLSFABNetworkClient *)networkClient + token:(FIRCLSDataCollectionToken *)token + settings:(FIRCLSSettings *)settings { + NSParameterAssert(appIdentifierModel); + NSParameterAssert(appEndPoint); + + self = [super initWithGoogleAppID:googleAppID token:token]; + if (self) { + _shouldCreate = shouldCreate; + _delegate = delegate; + _appIdentifierModel = appIdentifierModel; + _appEndpoint = appEndPoint; + _networkClient = networkClient; + _kitVersionsByKitBundleIdentifier = kitVersionsByKitBundleIdentifier.copy; + _settings = settings; + } + return self; +} + +- (void)main { + [self beginAppConfigure]; +} + +- (void)beginAppConfigure { + NSOutputStream *stream = [[NSOutputStream alloc] initToMemory]; + NSString *boundary = [FIRCLSMultipartMimeStreamEncoder generateBoundary]; + + FIRCLSMultipartMimeStreamEncoder *encoder = + [FIRCLSMultipartMimeStreamEncoder encoderWithStream:stream andBoundary:boundary]; + if (!encoder) { + FIRCLSErrorLog(@"Configure failed during onboarding"); + [self finishWithError:[self errorForCode:FIRCLSOnboardingErrorMultipartMimeConfiguration + userInfo:@{ + NSLocalizedDescriptionKey : @"Multipart mime encoder was nil" + }]]; + return; + } + + NSString *orgID = [self.settings orgID]; + if (!orgID) { + FIRCLSErrorLog(@"Could not onboard app with missing Organization ID"); + [self finishWithError:[self errorForCode:FIRCLSOnboardingErrorMultipartMimeConfiguration + userInfo:@{ + NSLocalizedDescriptionKey : @"Organization ID was nil" + }]]; + return; + } + + [encoder encode:^{ + [encoder addValue:orgID fieldName:@"org_id"]; + + [encoder addValue:self.settings.fetchedBundleID fieldName:@"app[identifier]"]; + [encoder addValue:self.appIdentifierModel.buildInstanceID + fieldName:@"app[instance_identifier]"]; + [encoder addValue:self.appIdentifierModel.displayName fieldName:@"app[name]"]; + [encoder addValue:self.appIdentifierModel.buildVersion fieldName:@"app[build_version]"]; + [encoder addValue:self.appIdentifierModel.displayVersion fieldName:@"app[display_version]"]; + [encoder addValue:@(self.appIdentifierModel.installSource) fieldName:@"app[source]"]; + [encoder addValue:self.appIdentifierModel.minimumSDKString + fieldName:@"app[minimum_sdk_version]"]; + [encoder addValue:self.appIdentifierModel.builtSDKString fieldName:@"app[built_sdk_version]"]; + [self.kitVersionsByKitBundleIdentifier + enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + NSString *formKey = [NSString stringWithFormat:@"%@[%@]", @"app[build][libraries]", key]; + [encoder addValue:obj fieldName:formKey]; + }]; + + [self.appIdentifierModel.architectureUUIDMap + enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [encoder addValue:key fieldName:@"app[slices][][arch]"]; + [encoder addValue:obj fieldName:@"app[slices][][uuid]"]; + }]; + }]; + + NSMutableURLRequest *request = [self onboardingRequestForAppCreate:self.shouldCreate]; + [request setValue:orgID forHTTPHeaderField:FIRCLSNetworkCrashlyticsOrgId]; + + [request setValue:encoder.contentTypeHTTPHeaderValue forHTTPHeaderField:@"Content-Type"]; + [request setValue:encoder.contentLengthHTTPHeaderValue forHTTPHeaderField:@"Content-Length"]; + [request setHTTPBody:[stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]]; + + // Retry only when onboarding an app for the first time, otherwise it'll overwhelm our servers + NSUInteger retryLimit = self.shouldCreate ? 10 : 1; + + [self.networkClient + startDataTaskWithRequest:request + retryLimit:retryLimit + completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { + self->_error = error; + if (!self.shouldCreate) { + [self.delegate onboardingOperation:self didCompleteAppUpdateWithError:error]; + } else { + [self.delegate onboardingOperation:self didCompleteAppCreationWithError:error]; + } + [self finishWithError:error]; + }]; +} + +#pragma mark private methods + +- (NSError *)errorForCode:(NSUInteger)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:FIRCLSOnboardingErrorDomain code:code userInfo:userInfo]; +} + +- (NSURL *)appCreateURL { + // https://update.crashlytics.com/spi/v1/platforms/mac/apps/com.crashlytics.mac + + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:self.appEndpoint]; + + [url appendComponent:@"/spi/v1/platforms/"]; + [url escapeAndAppendComponent:self.appIdentifierModel.platform]; + [url appendComponent:@"/apps"]; + + return url.URL; +} + +- (NSURL *)appUpdateURL { + // https://update.crashlytics.com/spi/v1/platforms/mac/apps/com.crashlytics.mac + + FIRCLSURLBuilder *url = [FIRCLSURLBuilder URLWithBase:[self appEndpoint]]; + + [url appendComponent:@"/spi/v1/platforms/"]; + [url escapeAndAppendComponent:self.appIdentifierModel.platform]; + [url appendComponent:@"/apps/"]; + [url escapeAndAppendComponent:self.settings.fetchedBundleID]; + + return url.URL; +} + +- (NSMutableURLRequest *)onboardingRequestForAppCreate:(BOOL)shouldCreate { + const NSTimeInterval timeout = 10.0; + NSURL *url = nil; + NSString *httpVerb = nil; + if (shouldCreate) { + httpVerb = @"POST"; + url = self.appCreateURL; + } else { + httpVerb = @"PUT"; + url = self.appUpdateURL; + } + NSMutableURLRequest *request = [self mutableRequestWithDefaultHTTPHeadersForURL:url + timeout:timeout]; + request.HTTPMethod = httpVerb; + return request; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.c new file mode 100644 index 00000000..efd25426 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.c @@ -0,0 +1,404 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <string.h> + +#if CLS_COMPACT_UNWINDING_SUPPORTED + +#pragma mark Parsing +bool FIRCLSCompactUnwindInit(FIRCLSCompactUnwindContext* context, + const void* unwindInfo, + const void* ehFrame, + uintptr_t loadAddress) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLog("Error: invalid context passed to compact unwind init"); + return false; + } + if (!FIRCLSIsValidPointer(unwindInfo)) { + FIRCLSSDKLog("Error: invalid unwind info passed to compact unwind init"); + return false; + } + if (!FIRCLSIsValidPointer(loadAddress)) { + FIRCLSSDKLog("Error: invalid load address passed to compact unwind init"); + return false; + } + + memset(context, 0, sizeof(FIRCLSCompactUnwindContext)); + + if (!FIRCLSReadMemory((vm_address_t)unwindInfo, &context->unwindHeader, + sizeof(struct unwind_info_section_header))) { + FIRCLSSDKLog("Error: could not read memory contents of unwindInfo\n"); + return false; + } + + if (context->unwindHeader.version != UNWIND_SECTION_VERSION) { + FIRCLSSDKLog("Error: bad unwind_info structure version (%d != %d)\n", + context->unwindHeader.version, UNWIND_SECTION_VERSION); + return false; + } + + // copy in the values + context->unwindInfo = unwindInfo; + context->ehFrame = ehFrame; + context->loadAddress = loadAddress; + + return true; +} + +void* FIRCLSCompactUnwindGetIndexData(FIRCLSCompactUnwindContext* context) { + return (void*)((uintptr_t)context->unwindInfo + + (uintptr_t)context->unwindHeader.indexSectionOffset); +} + +compact_unwind_encoding_t* FIRCLSCompactUnwindGetCommonEncodings( + FIRCLSCompactUnwindContext* context) { + return (compact_unwind_encoding_t*)((uintptr_t)context->unwindInfo + + (uintptr_t) + context->unwindHeader.commonEncodingsArraySectionOffset); +} + +void* FIRCLSCompactUnwindGetSecondLevelData(FIRCLSCompactUnwindContext* context) { + return (void*)((uintptr_t)context->unwindInfo + + context->indexHeader.secondLevelPagesSectionOffset); +} + +uintptr_t FIRCLSCompactUnwindGetIndexFunctionOffset(FIRCLSCompactUnwindContext* context) { + return context->loadAddress + context->indexHeader.functionOffset; +} +uintptr_t FIRCLSCompactUnwindGetTargetAddress(FIRCLSCompactUnwindContext* context, uintptr_t pc) { + uintptr_t offset = FIRCLSCompactUnwindGetIndexFunctionOffset(context); + + if (pc <= offset) { + FIRCLSSDKLog("Error: PC is invalid\n"); + return 0; + } + + return pc - offset; +} + +#pragma mark - Parsing and Lookup +bool FIRCLSCompactUnwindLookupFirstLevel(FIRCLSCompactUnwindContext* context, uintptr_t address) { + if (!context) { + return false; + } + + // In practice, it appears that there always one more first level entry + // than required. This actually makes sense, since we have to use this + // info to check if we are in range. This implies there must be + // at least 2 indices at a minimum. + + uint32_t indexCount = context->unwindHeader.indexCount; + if (indexCount < 2) { + return false; + } + + // make sure our address is valid + if (address < context->loadAddress) { + return false; + } + + struct unwind_info_section_header_index_entry* indexEntries = + FIRCLSCompactUnwindGetIndexData(context); + if (!indexEntries) { + return false; + } + + address -= context->loadAddress; // search relative to zero + + // minus one because of the extra entry - see comment above + for (uint32_t index = 0; index < indexCount - 1; ++index) { + uint32_t value = indexEntries[index].functionOffset; + uint32_t nextValue = indexEntries[index + 1].functionOffset; + + if (address >= value && address < nextValue) { + context->firstLevelNextFunctionOffset = nextValue; + context->indexHeader = indexEntries[index]; + return true; + } + } + + return false; +} + +uint32_t FIRCLSCompactUnwindGetSecondLevelPageKind(FIRCLSCompactUnwindContext* context) { + if (!context) { + return 0; + } + + return *(uint32_t*)FIRCLSCompactUnwindGetSecondLevelData(context); +} + +bool FIRCLSCompactUnwindLookupSecondLevelRegular(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + FIRCLSSDKLog("Encountered a regular second-level page\n"); + return false; +} + +// this only works for compressed entries right now +bool FIRCLSCompactUnwindBinarySearchSecondLevel(uintptr_t address, + uint32_t* index, + uint16_t entryCount, + uint32_t* entryArray) { + if (!index || !entryArray) { + return false; + } + + if (entryCount == 0) { + return false; + } + + if (address == 0) { + return false; + } + + uint32_t highIndex = entryCount; + *index = 0; + + while (*index < highIndex) { + uint32_t midIndex = (*index + highIndex) / 2; + + // FIRCLSSDKLog("%u %u %u\n", *index, midIndex, highIndex); + + uintptr_t value = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entryArray[midIndex]); + + if (value > address) { + if (highIndex == midIndex) { + return false; + } + + highIndex = midIndex; + continue; + } + + *index = midIndex; + + // are we at the end of the array? + if (midIndex == entryCount - 1) { + return false; + } + + uintptr_t nextValue = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entryArray[midIndex + 1]); + if (nextValue > address) { + // we've found it + break; + } + + *index += 1; + } + + // check to make sure we're still within bounds + return *index < entryCount; +} + +bool FIRCLSCompactUnwindLookupSecondLevelCompressed(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + if (!context || !result) { + return false; + } + + void* ptr = FIRCLSCompactUnwindGetSecondLevelData(context); + + if (!ptr) { + return false; + } + + memset(result, 0, sizeof(FIRCLSCompactUnwindResult)); + + struct unwind_info_compressed_second_level_page_header* header = + (struct unwind_info_compressed_second_level_page_header*)ptr; + + // adjust address + uintptr_t targetAddress = FIRCLSCompactUnwindGetTargetAddress(context, pc); + + uint32_t* entryArray = ptr + header->entryPageOffset; + + uint32_t index = 0; + + if (!FIRCLSCompactUnwindBinarySearchSecondLevel(targetAddress, &index, header->entryCount, + entryArray)) { + FIRCLSSDKLogInfo("Unable to find PC in second level\n"); + return false; + } + + uint32_t entry = entryArray[index]; + + // Computing the fuction start address is easy + result->functionStart = UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entry) + + FIRCLSCompactUnwindGetIndexFunctionOffset(context); + + // Computing the end is more complex, because we could be on the last entry. In that case, we + // cannot use the next value as the end. + result->functionEnd = context->loadAddress; + if (index < header->entryCount - 1) { + result->functionEnd += UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(entryArray[index + 1]) + + context->indexHeader.functionOffset; + } else { + result->functionEnd += context->firstLevelNextFunctionOffset; + } + + // FIRCLSSDKLog("Located %lx => %lx %lx\n", pc, result->functionStart, result->functionEnd); + + if ((pc < result->functionStart) || (pc >= result->functionEnd)) { + FIRCLSSDKLog("PC does not match computed function range\n"); + return false; + } + + uint32_t encodingIndex = UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(entry); + + // encoding could be in the common array + if (encodingIndex < context->unwindHeader.commonEncodingsArrayCount) { + result->encoding = FIRCLSCompactUnwindGetCommonEncodings(context)[encodingIndex]; + + // FIRCLSSDKLog("Entry has common encoding: 0x%x\n", result->encoding); + } else { + encodingIndex = encodingIndex - context->unwindHeader.commonEncodingsArrayCount; + + compact_unwind_encoding_t* encodings = ptr + header->encodingsPageOffset; + + result->encoding = encodings[encodingIndex]; + + // FIRCLSSDKLog("Entry has compressed encoding: 0x%x\n", result->encoding); + } + + if (result->encoding == 0) { + FIRCLSSDKLogInfo("Entry has has no unwind info\n"); + return false; + } + + return true; +} + +bool FIRCLSCompactUnwindLookupSecondLevel(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + switch (FIRCLSCompactUnwindGetSecondLevelPageKind(context)) { + case UNWIND_SECOND_LEVEL_REGULAR: + FIRCLSSDKLogInfo("Found a second level regular header\n"); + if (FIRCLSCompactUnwindLookupSecondLevelRegular(context, pc, result)) { + return true; + } + break; + case UNWIND_SECOND_LEVEL_COMPRESSED: + FIRCLSSDKLogInfo("Found a second level compressed header\n"); + if (FIRCLSCompactUnwindLookupSecondLevelCompressed(context, pc, result)) { + return true; + } + break; + default: + FIRCLSSDKLogError("Unrecognized header kind - unable to continue\n"); + break; + } + + return false; +} + +bool FIRCLSCompactUnwindLookup(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result) { + if (!context || !result) { + return false; + } + + // step 1 - find the pc in the first-level index + if (!FIRCLSCompactUnwindLookupFirstLevel(context, pc)) { + FIRCLSSDKLogWarn("Unable to find pc in first level\n"); + return false; + } + + FIRCLSSDKLogDebug("Found first level (second => %u)\n", + context->indexHeader.secondLevelPagesSectionOffset); + + // step 2 - use that info to find the second-level information + // that second actually has the encoding info we're looking for. + if (!FIRCLSCompactUnwindLookupSecondLevel(context, pc, result)) { + FIRCLSSDKLogInfo("Second-level PC lookup failed\n"); + return false; + } + + return true; +} + +#pragma mark - Unwinding +bool FIRCLSCompactUnwindLookupAndCompute(FIRCLSCompactUnwindContext* context, + FIRCLSThreadContext* registers) { + if (!context || !registers) { + return false; + } + + uintptr_t pc = FIRCLSThreadContextGetPC(registers); + + // little sanity check + if (pc < context->loadAddress) { + return false; + } + + FIRCLSCompactUnwindResult result; + + memset(&result, 0, sizeof(result)); + + if (!FIRCLSCompactUnwindLookup(context, pc, &result)) { + FIRCLSSDKLogInfo("Unable to lookup compact unwind for pc %p\n", (void*)pc); + return false; + } + + // Ok, armed with the encoding, we can actually attempt to modify the registers. Because + // the encoding is arch-specific, this function has to be defined per-arch. + if (!FIRCLSCompactUnwindComputeRegisters(context, &result, registers)) { + FIRCLSSDKLogError("Failed to compute registers\n"); + return false; + } + + return true; +} + +#if CLS_DWARF_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindDwarfFrame(FIRCLSCompactUnwindContext* context, + uintptr_t dwarfOffset, + FIRCLSThreadContext* registers) { + if (!context || !registers) { + return false; + } + + // Everyone's favorite! Dwarf unwinding! + FIRCLSSDKLogInfo("Trying to read dwarf data with offset %lx\n", dwarfOffset); + + FIRCLSDwarfCFIRecord record; + + if (!FIRCLSDwarfParseCFIFromFDERecordOffset(&record, context->ehFrame, dwarfOffset)) { + FIRCLSSDKLogError("Unable to init FDE\n"); + return false; + } + + if (!FIRCLSDwarfUnwindComputeRegisters(&record, registers)) { + FIRCLSSDKLogError("Failed to compute DWARF registers\n"); + return false; + } + + return true; +} +#endif + +#else +INJECT_STRIP_SYMBOL(compact_unwind) +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h new file mode 100644 index 00000000..a4698e72 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h @@ -0,0 +1,68 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" + +// We have to pack the arrays defined in this header, so +// we can reason about pointer math. +#pragma pack(push) +#pragma pack(1) +#include <mach-o/compact_unwind_encoding.h> +#pragma pack(pop) + +// First masks out the value, and then shifts the value by the number +// of zeros in the mask. __builtin_ctz returns the number of trailing zeros. +// Its output is undefined if the input is zero. +#define GET_BITS_WITH_MASK(value, mask) ((value & mask) >> (mask == 0 ? 0 : __builtin_ctz(mask))) + +typedef struct { + const void* unwindInfo; + const void* ehFrame; + uintptr_t loadAddress; + + struct unwind_info_section_header unwindHeader; + struct unwind_info_section_header_index_entry indexHeader; + uint32_t firstLevelNextFunctionOffset; +} FIRCLSCompactUnwindContext; + +typedef struct { + compact_unwind_encoding_t encoding; + uintptr_t functionStart; + uintptr_t functionEnd; + uintptr_t lsda; + uintptr_t personality; + +} FIRCLSCompactUnwindResult; + +bool FIRCLSCompactUnwindInit(FIRCLSCompactUnwindContext* context, + const void* unwindInfo, + const void* ehFrame, + uintptr_t loadAddress); +void* FIRCLSCompactUnwindGetIndexData(FIRCLSCompactUnwindContext* context); +void* FIRCLSCompactUnwindGetSecondLevelData(FIRCLSCompactUnwindContext* context); +bool FIRCLSCompactUnwindFindFirstLevelIndex(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + uint32_t* index); + +bool FIRCLSCompactUnwindDwarfFrame(FIRCLSCompactUnwindContext* context, + uintptr_t dwarfOffset, + FIRCLSThreadContext* registers); +bool FIRCLSCompactUnwindLookupAndCompute(FIRCLSCompactUnwindContext* context, + FIRCLSThreadContext* registers); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h new file mode 100644 index 00000000..b918198b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h @@ -0,0 +1,28 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h" +#pragma pack(push, 1) +#include <mach-o/compact_unwind_encoding.h> +#pragma pack(pop) + +bool FIRCLSCompactUnwindLookup(FIRCLSCompactUnwindContext* context, + uintptr_t pc, + FIRCLSCompactUnwindResult* result); + +bool FIRCLSCompactUnwindComputeRegisters(FIRCLSCompactUnwindContext* context, + FIRCLSCompactUnwindResult* result, + FIRCLSThreadContext* registers); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.c new file mode 100644 index 00000000..2bb37c1b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.c @@ -0,0 +1,238 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#include "Crashlytics/third_party/libunwind/dwarf.h" + +#include <string.h> + +#if CLS_DWARF_UNWINDING_SUPPORTED + +uint8_t FIRCLSParseUint8AndAdvance(const void** cursor) { + uint8_t tmp = **(uint8_t**)cursor; + + *cursor += sizeof(uint8_t); + + return tmp; +} + +uint16_t FIRCLSParseUint16AndAdvance(const void** cursor) { + uint16_t tmp = **(uint16_t**)cursor; + + *cursor += sizeof(uint16_t); + + return tmp; +} + +int16_t FIRCLSParseInt16AndAdvance(const void** cursor) { + int16_t tmp = **(int16_t**)cursor; + + *cursor += sizeof(int16_t); + + return tmp; +} + +uint32_t FIRCLSParseUint32AndAdvance(const void** cursor) { + uint32_t tmp = **(uint32_t**)cursor; + + *cursor += sizeof(uint32_t); + + return tmp; +} + +int32_t FIRCLSParseInt32AndAdvance(const void** cursor) { + int32_t tmp = **(int32_t**)cursor; + + *cursor += sizeof(int32_t); + + return tmp; +} + +uint64_t FIRCLSParseUint64AndAdvance(const void** cursor) { + uint64_t tmp = **(uint64_t**)cursor; + + *cursor += sizeof(uint64_t); + + return tmp; +} + +int64_t FIRCLSParseInt64AndAdvance(const void** cursor) { + int64_t tmp = **(int64_t**)cursor; + + *cursor += sizeof(int64_t); + + return tmp; +} + +uintptr_t FIRCLSParsePointerAndAdvance(const void** cursor) { + uintptr_t tmp = **(uintptr_t**)cursor; + + *cursor += sizeof(uintptr_t); + + return tmp; +} + +// Signed and Unsigned LEB128 decoding algorithms taken from Wikipedia - +// http://en.wikipedia.org/wiki/LEB128 +uint64_t FIRCLSParseULEB128AndAdvance(const void** cursor) { + uint64_t result = 0; + char shift = 0; + + for (int i = 0; i < sizeof(uint64_t); ++i) { + char byte; + + byte = **(uint8_t**)cursor; + + *cursor += 1; + + result |= ((0x7F & byte) << shift); + if ((0x80 & byte) == 0) { + break; + } + + shift += 7; + } + + return result; +} + +int64_t FIRCLSParseLEB128AndAdvance(const void** cursor) { + uint64_t result = 0; + char shift = 0; + char size = sizeof(int64_t) * 8; + char byte = 0; + + for (int i = 0; i < sizeof(uint64_t); ++i) { + byte = **(uint8_t**)cursor; + + *cursor += 1; + + result |= ((0x7F & byte) << shift); + shift += 7; + + /* sign bit of byte is second high order bit (0x40) */ + if ((0x80 & byte) == 0) { + break; + } + } + + if ((shift < size) && (0x40 & byte)) { + // sign extend + result |= -(1 << shift); + } + + return result; +} + +const char* FIRCLSParseStringAndAdvance(const void** cursor) { + const char* string; + + string = (const char*)(*cursor); + + // strlen doesn't include the null character, which we need to advance past + *cursor += strlen(string) + 1; + + return string; +} + +uint64_t FIRCLSParseRecordLengthAndAdvance(const void** cursor) { + uint64_t length; + + length = FIRCLSParseUint32AndAdvance(cursor); + if (length == DWARF_EXTENDED_LENGTH_FLAG) { + length = FIRCLSParseUint64AndAdvance(cursor); + } + + return length; +} + +uintptr_t FIRCLSParseAddressWithEncodingAndAdvance(const void** cursor, uint8_t encoding) { + if (encoding == DW_EH_PE_omit) { + return 0; + } + + if (!cursor) { + return CLS_INVALID_ADDRESS; + } + + if (!*cursor) { + return CLS_INVALID_ADDRESS; + } + + intptr_t inputAddr = (intptr_t)*cursor; + intptr_t addr; + + switch (encoding & DW_EH_PE_VALUE_MASK) { + case DW_EH_PE_ptr: + // 32 or 64 bits + addr = FIRCLSParsePointerAndAdvance(cursor); + break; + case DW_EH_PE_uleb128: + addr = (intptr_t)FIRCLSParseULEB128AndAdvance(cursor); + break; + case DW_EH_PE_udata2: + addr = FIRCLSParseUint16AndAdvance(cursor); + break; + case DW_EH_PE_udata4: + addr = FIRCLSParseUint32AndAdvance(cursor); + break; + case DW_EH_PE_udata8: + addr = (intptr_t)FIRCLSParseUint64AndAdvance(cursor); + break; + case DW_EH_PE_sleb128: + addr = (intptr_t)FIRCLSParseLEB128AndAdvance(cursor); + break; + case DW_EH_PE_sdata2: + addr = FIRCLSParseInt16AndAdvance(cursor); + break; + case DW_EH_PE_sdata4: + addr = FIRCLSParseInt32AndAdvance(cursor); + break; + case DW_EH_PE_sdata8: + addr = (intptr_t)FIRCLSParseInt64AndAdvance(cursor); + break; + default: + FIRCLSSDKLog("Unhandled: encoding 0x%02x\n", encoding); + return CLS_INVALID_ADDRESS; + } + + // and now apply the relative offset + switch (encoding & DW_EH_PE_RELATIVE_OFFSET_MASK) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + addr += inputAddr; + break; + default: + FIRCLSSDKLog("Unhandled: relative encoding 0x%02x\n", encoding); + return CLS_INVALID_ADDRESS; + } + + // Here's a crazy one. It seems this encoding means you actually look up + // the value of the address using the result address itself + if (encoding & DW_EH_PE_indirect) { + if (!addr) { + return CLS_INVALID_ADDRESS; + } + + addr = *(uintptr_t*)addr; + } + + return addr; +} +#else +INJECT_STRIP_SYMBOL(data_parsing) +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h new file mode 100644 index 00000000..0158cc95 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h @@ -0,0 +1,46 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdint.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" + +#if CLS_DWARF_UNWINDING_SUPPORTED + +#if CLS_CPU_64BIT +#define CLS_INVALID_ADDRESS (0xffffffffffffffff) +#else +#define CLS_INVALID_ADDRESS (0xffffffff) +#endif + +// basic data types +uint8_t FIRCLSParseUint8AndAdvance(const void** cursor); +uint16_t FIRCLSParseUint16AndAdvance(const void** cursor); +int16_t FIRCLSParseInt16AndAdvance(const void** cursor); +uint32_t FIRCLSParseUint32AndAdvance(const void** cursor); +int32_t FIRCLSParseInt32AndAdvance(const void** cursor); +uint64_t FIRCLSParseUint64AndAdvance(const void** cursor); +int64_t FIRCLSParseInt64AndAdvance(const void** cursor); +uintptr_t FIRCLSParsePointerAndAdvance(const void** cursor); +uint64_t FIRCLSParseULEB128AndAdvance(const void** cursor); +int64_t FIRCLSParseLEB128AndAdvance(const void** cursor); +const char* FIRCLSParseStringAndAdvance(const void** cursor); + +// FDE/CIE-specifc structures +uint64_t FIRCLSParseRecordLengthAndAdvance(const void** cursor); +uintptr_t FIRCLSParseAddressWithEncodingAndAdvance(const void** cursor, uint8_t encoding); + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.c new file mode 100644 index 00000000..ef975fee --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.c @@ -0,0 +1,453 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#include "Crashlytics/third_party/libunwind/dwarf.h" + +#if CLS_DWARF_UNWINDING_SUPPORTED + +static bool FIRCLSDwarfExpressionMachineExecute_bregN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode); +static bool FIRCLSDwarfExpressionMachineExecute_deref(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_plus_uconst(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_and(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_plus(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_dup(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_swap(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_deref_size(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_ne(FIRCLSDwarfExpressionMachine *machine); +static bool FIRCLSDwarfExpressionMachineExecute_litN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode); + +#pragma mark - +#pragma mark Stack Implementation +void FIRCLSDwarfExpressionStackInit(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSIsValidPointer(stack)) { + return; + } + + memset(stack, 0, sizeof(FIRCLSDwarfExpressionStack)); + + stack->pointer = stack->buffer; +} + +bool FIRCLSDwarfExpressionStackIsValid(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSIsValidPointer(stack)) { + return false; + } + + // check for valid stack pointer + if (stack->pointer < stack->buffer) { + return false; + } + + if (stack->pointer > stack->buffer + CLS_DWARF_EXPRESSION_STACK_SIZE) { + return false; + } + + return true; +} + +bool FIRCLSDwarfExpressionStackPush(FIRCLSDwarfExpressionStack *stack, intptr_t value) { + if (!FIRCLSDwarfExpressionStackIsValid(stack)) { + return false; + } + + if (stack->pointer == stack->buffer + CLS_DWARF_EXPRESSION_STACK_SIZE) { + // overflow + stack->pointer = NULL; + return false; + } + + *(stack->pointer) = value; + stack->pointer += 1; + + return true; +} + +intptr_t FIRCLSDwarfExpressionStackPeek(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSDwarfExpressionStackIsValid(stack)) { + return 0; + } + + if (stack->pointer == stack->buffer) { + // underflow + stack->pointer = NULL; + return 0; + } + + return *(stack->pointer - 1); +} + +intptr_t FIRCLSDwarfExpressionStackPop(FIRCLSDwarfExpressionStack *stack) { + if (!FIRCLSDwarfExpressionStackIsValid(stack)) { + return 0; + } + + if (stack->pointer == stack->buffer) { + // underflow + stack->pointer = NULL; + return 0; + } + + stack->pointer -= 1; + + return *(stack->pointer); +} + +#pragma mark - +#pragma mark Machine API +bool FIRCLSDwarfExpressionMachineInit(FIRCLSDwarfExpressionMachine *machine, + const void *cursor, + const FIRCLSThreadContext *registers, + intptr_t stackValue) { + if (!FIRCLSIsValidPointer(machine)) { + return false; + } + + memset(machine, 0, sizeof(FIRCLSDwarfExpressionMachine)); + + if (!FIRCLSIsValidPointer(cursor)) { + return false; + } + + machine->dataCursor = cursor; + machine->registers = registers; + + FIRCLSDwarfExpressionStackInit(&machine->stack); + + return FIRCLSDwarfExpressionStackPush(&machine->stack, stackValue); +} + +bool FIRCLSDwarfExpressionMachinePrepareForExecution(FIRCLSDwarfExpressionMachine *machine) { + if (!FIRCLSIsValidPointer(machine)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + uint64_t expressionLength = FIRCLSParseULEB128AndAdvance(&machine->dataCursor); + + if (expressionLength == 0) { + FIRCLSSDKLog("Error: DWARF expression length is zero\n"); + return false; + } + + machine->endAddress = machine->dataCursor + expressionLength; + + return true; +} + +bool FIRCLSDwarfExpressionMachineIsFinished(FIRCLSDwarfExpressionMachine *machine) { + if (!FIRCLSIsValidPointer(machine)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return true; + } + + if (!FIRCLSIsValidPointer(machine->endAddress) || !FIRCLSIsValidPointer(machine->dataCursor)) { + FIRCLSSDKLog("Error: DWARF machine pointers invalid\n"); + return true; + } + + if (!FIRCLSDwarfExpressionStackIsValid(&machine->stack)) { + FIRCLSSDKLog("Error: DWARF machine stack invalid\n"); + return true; + } + + return machine->dataCursor >= machine->endAddress; +} + +bool FIRCLSDwarfExpressionMachineGetResult(FIRCLSDwarfExpressionMachine *machine, + intptr_t *result) { + if (!FIRCLSIsValidPointer(machine) || !FIRCLSIsValidPointer(result)) { + return false; + } + + if (machine->dataCursor != machine->endAddress) { + FIRCLSSDKLog("Error: DWARF expression hasn't completed execution\n"); + return false; + } + + *result = FIRCLSDwarfExpressionStackPeek(&machine->stack); + + return FIRCLSDwarfExpressionStackIsValid(&machine->stack); +} + +bool FIRCLSDwarfExpressionMachineExecuteNextOpcode(FIRCLSDwarfExpressionMachine *machine) { + if (!FIRCLSIsValidPointer(machine)) { + return false; + } + + const uint8_t opcode = FIRCLSParseUint8AndAdvance(&machine->dataCursor); + + bool success = false; + + switch (opcode) { + case DW_OP_deref: + success = FIRCLSDwarfExpressionMachineExecute_deref(machine); + break; + case DW_OP_dup: + success = FIRCLSDwarfExpressionMachineExecute_dup(machine); + break; + case DW_OP_and: + success = FIRCLSDwarfExpressionMachineExecute_and(machine); + break; + case DW_OP_plus: + success = FIRCLSDwarfExpressionMachineExecute_plus(machine); + break; + case DW_OP_swap: + success = FIRCLSDwarfExpressionMachineExecute_swap(machine); + break; + case DW_OP_plus_uconst: + success = FIRCLSDwarfExpressionMachineExecute_plus_uconst(machine); + break; + case DW_OP_ne: + success = FIRCLSDwarfExpressionMachineExecute_ne(machine); + break; + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + success = FIRCLSDwarfExpressionMachineExecute_litN(machine, opcode); + break; + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + success = FIRCLSDwarfExpressionMachineExecute_bregN(machine, opcode); + break; + case DW_OP_deref_size: + success = FIRCLSDwarfExpressionMachineExecute_deref_size(machine); + break; + default: + FIRCLSSDKLog("Error: Unrecognized DWARF expression opcode 0x%x\n", opcode); + return false; + } + + return success; +} + +#pragma mark - +#pragma mark Helpers +static intptr_t FIRCLSDwarfExpressionMachineStackPop(FIRCLSDwarfExpressionMachine *machine) { + return FIRCLSDwarfExpressionStackPop(&machine->stack); +} + +static bool FIRCLSDwarfExpressionMachineStackPush(FIRCLSDwarfExpressionMachine *machine, + intptr_t value) { + return FIRCLSDwarfExpressionStackPush(&machine->stack, value); +} + +#pragma mark - +#pragma mark Opcode Implementations +static bool FIRCLSDwarfExpressionMachineExecute_bregN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode) { + // find the register number, compute offset value, push + const uint8_t regNum = opcode - DW_OP_breg0; + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: DW_OP_breg invalid register number\n"); + return false; + } + + int64_t offset = FIRCLSParseLEB128AndAdvance(&machine->dataCursor); + + FIRCLSSDKLog("DW_OP_breg %d value %d\n", regNum, (int)offset); + + const intptr_t value = + FIRCLSDwarfUnwindGetRegisterValue(machine->registers, regNum) + (intptr_t)offset; + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_deref(FIRCLSDwarfExpressionMachine *machine) { + // pop stack, dereference, push result + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + FIRCLSSDKLog("DW_OP_deref value %p\n", (void *)value); + + if (!FIRCLSReadMemory(value, &value, sizeof(value))) { + FIRCLSSDKLog("Error: DW_OP_deref failed to read memory\n"); + return false; + } + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_plus_uconst(FIRCLSDwarfExpressionMachine *machine) { + // pop stack, add constant, push result + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value += FIRCLSParseULEB128AndAdvance(&machine->dataCursor); + + FIRCLSSDKLog("DW_OP_plus_uconst value %lu\n", value); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_and(FIRCLSDwarfExpressionMachine *machine) { + FIRCLSSDKLog("DW_OP_plus_and\n"); + + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value = value & FIRCLSDwarfExpressionMachineStackPop(machine); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_plus(FIRCLSDwarfExpressionMachine *machine) { + FIRCLSSDKLog("DW_OP_plus\n"); + + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value = value + FIRCLSDwarfExpressionMachineStackPop(machine); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_dup(FIRCLSDwarfExpressionMachine *machine) { + // duplicate top of stack + intptr_t value = FIRCLSDwarfExpressionStackPeek(&machine->stack); + + FIRCLSSDKLog("DW_OP_dup value %lu\n", value); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_swap(FIRCLSDwarfExpressionMachine *machine) { + // swap top two values on the stack + intptr_t valueA = FIRCLSDwarfExpressionMachineStackPop(machine); + intptr_t valueB = FIRCLSDwarfExpressionMachineStackPop(machine); + + FIRCLSSDKLog("DW_OP_swap\n"); + + if (!FIRCLSDwarfExpressionMachineStackPush(machine, valueA)) { + return false; + } + + return FIRCLSDwarfExpressionMachineStackPush(machine, valueB); +} + +static bool FIRCLSDwarfExpressionMachineExecute_deref_size(FIRCLSDwarfExpressionMachine *machine) { + // pop stack, dereference variable sized value, push result + const void *address = (const void *)FIRCLSDwarfExpressionMachineStackPop(machine); + const uint8_t readSize = FIRCLSParseUint8AndAdvance(&machine->dataCursor); + intptr_t value = 0; + + FIRCLSSDKLog("DW_OP_deref_size %p size %u\n", address, readSize); + + switch (readSize) { + case 1: + value = FIRCLSParseUint8AndAdvance(&address); + break; + case 2: + value = FIRCLSParseUint16AndAdvance(&address); + break; + case 4: + value = FIRCLSParseUint32AndAdvance(&address); + break; + case 8: + // this is a little funky, as an 8 here really doesn't make sense for 32-bit platforms + value = (intptr_t)FIRCLSParseUint64AndAdvance(&address); + break; + default: + FIRCLSSDKLog("Error: unrecognized DW_OP_deref_size argument %x\n", readSize); + return false; + } + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_ne(FIRCLSDwarfExpressionMachine *machine) { + FIRCLSSDKLog("DW_OP_ne\n"); + + intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine); + + value = value != FIRCLSDwarfExpressionMachineStackPop(machine); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +static bool FIRCLSDwarfExpressionMachineExecute_litN(FIRCLSDwarfExpressionMachine *machine, + uint8_t opcode) { + const uint8_t value = opcode - DW_OP_lit0; + + FIRCLSSDKLog("DW_OP_lit %u\n", value); + + return FIRCLSDwarfExpressionMachineStackPush(machine, value); +} + +#else +INJECT_STRIP_SYMBOL(dwarf_expression_machine) +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h new file mode 100644 index 00000000..2fb46288 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h @@ -0,0 +1,55 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" + +#define CLS_DWARF_EXPRESSION_STACK_SIZE (100) + +#if CLS_DWARF_UNWINDING_SUPPORTED + +typedef struct { + intptr_t buffer[CLS_DWARF_EXPRESSION_STACK_SIZE]; + intptr_t *pointer; +} FIRCLSDwarfExpressionStack; + +typedef struct { + FIRCLSDwarfExpressionStack stack; + const void *dataCursor; + const void *endAddress; + const FIRCLSThreadContext *registers; +} FIRCLSDwarfExpressionMachine; + +void FIRCLSDwarfExpressionStackInit(FIRCLSDwarfExpressionStack *stack); +bool FIRCLSDwarfExpressionStackIsValid(FIRCLSDwarfExpressionStack *stack); +bool FIRCLSDwarfExpressionStackPush(FIRCLSDwarfExpressionStack *stack, intptr_t value); +intptr_t FIRCLSDwarfExpressionStackPeek(FIRCLSDwarfExpressionStack *stack); +intptr_t FIRCLSDwarfExpressionStackPop(FIRCLSDwarfExpressionStack *stack); + +bool FIRCLSDwarfExpressionMachineInit(FIRCLSDwarfExpressionMachine *machine, + const void *cursor, + const FIRCLSThreadContext *registers, + intptr_t stackValue); +bool FIRCLSDwarfExpressionMachinePrepareForExecution(FIRCLSDwarfExpressionMachine *machine); +bool FIRCLSDwarfExpressionMachineIsFinished(FIRCLSDwarfExpressionMachine *machine); +bool FIRCLSDwarfExpressionMachineGetResult(FIRCLSDwarfExpressionMachine *machine, intptr_t *result); + +bool FIRCLSDwarfExpressionMachineExecuteNextOpcode(FIRCLSDwarfExpressionMachine *machine); + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c new file mode 100644 index 00000000..5b15a358 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c @@ -0,0 +1,1002 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfExpressionMachine.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#include "Crashlytics/third_party/libunwind/dwarf.h" + +#include <string.h> + +#if CLS_DWARF_UNWINDING_SUPPORTED + +#define FIRCLSDwarfLog(__FORMAT__, ...) FIRCLSSDKLog(__FORMAT__, ##__VA_ARGS__) + +#define CLS_DWARF_EXPRESSION_STACK_SIZE (100) + +#pragma mark Prototypes +static bool FIRCLSDwarfParseAndProcessAugmentation(DWARFCIERecord* record, const void** ptr); + +#pragma mark - Record Parsing +bool FIRCLSDwarfParseCIERecord(DWARFCIERecord* cie, const void* ptr) { + if (!cie || !ptr) { + return false; + } + + memset(cie, 0, sizeof(DWARFCIERecord)); + + cie->length = FIRCLSParseRecordLengthAndAdvance(&ptr); + if (cie->length == 0) { + FIRCLSSDKLog("Error: CIE length invalid\n"); + return false; + } + + // the length does not include the length field(s) themselves + const void* endAddress = ptr + cie->length; + + if (FIRCLSParseUint32AndAdvance(&ptr) != DWARF_CIE_ID_CIE_FLAG) { + FIRCLSSDKLog("Error: CIE flag not found\n"); + } + + cie->version = FIRCLSParseUint8AndAdvance(&ptr); + if (cie->version != 1 && cie->version != 3) { + FIRCLSSDKLog("Error: CIE version %u unsupported\n", cie->version); + } + + cie->pointerEncoding = DW_EH_PE_absptr; + cie->lsdaEncoding = DW_EH_PE_absptr; + + cie->augmentation = FIRCLSParseStringAndAdvance(&ptr); + cie->codeAlignFactor = FIRCLSParseULEB128AndAdvance(&ptr); + cie->dataAlignFactor = FIRCLSParseLEB128AndAdvance(&ptr); + + switch (cie->version) { + case 1: + cie->returnAddressRegister = FIRCLSParseUint8AndAdvance(&ptr); + break; + case 3: + cie->returnAddressRegister = FIRCLSParseULEB128AndAdvance(&ptr); + break; + default: + FIRCLSSDKLog("Error: CIE version %u unsupported\n", cie->version); + return false; + } + + if (!FIRCLSDwarfParseAndProcessAugmentation(cie, &ptr)) { + return false; + } + + cie->instructions.data = ptr; + cie->instructions.length = (uint32_t)(endAddress - ptr); + + return true; +} + +static bool FIRCLSDwarfParseAndProcessAugmentation(DWARFCIERecord* record, const void** ptr) { + if (!record || !ptr) { + return false; + } + + if (!record->augmentation) { + return false; + } + + if (record->augmentation[0] == 0) { + return true; + } + + if (record->augmentation[0] != 'z') { + FIRCLSSDKLog("Error: Unimplemented: augmentation string %s\n", record->augmentation); + return false; + } + + size_t stringLength = strlen(record->augmentation); + + uint64_t dataLength = FIRCLSParseULEB128AndAdvance(ptr); + const void* ending = *ptr + dataLength; + + // start at 1 because we know the first character is a 'z' + for (size_t i = 1; i < stringLength; ++i) { + switch (record->augmentation[i]) { + case 'L': + // There is an LSDA pointer encoding present. The actual address of the LSDA + // is in the FDE + record->lsdaEncoding = FIRCLSParseUint8AndAdvance(ptr); + break; + case 'R': + // There is a pointer encoding present, used for all addresses in an FDE. + record->pointerEncoding = FIRCLSParseUint8AndAdvance(ptr); + break; + case 'P': + // Two arguments. A pointer encoding, and a pointer to a personality function encoded + // with that value. + record->personalityEncoding = FIRCLSParseUint8AndAdvance(ptr); + record->personalityFunction = + FIRCLSParseAddressWithEncodingAndAdvance(ptr, record->personalityEncoding); + if (record->personalityFunction == CLS_INVALID_ADDRESS) { + FIRCLSSDKLog("Error: Found an invalid start address\n"); + return false; + } + break; + case 'S': + record->signalFrame = true; + break; + default: + FIRCLSSDKLog("Error: Unhandled augmentation string entry %c\n", record->augmentation[i]); + return false; + } + + // small sanity check + if (*ptr > ending) { + return false; + } + } + + return true; +} + +bool FIRCLSDwarfParseFDERecord(DWARFFDERecord* fdeRecord, + bool parseCIE, + DWARFCIERecord* cieRecord, + const void* ptr) { + if (!fdeRecord || !cieRecord || !ptr) { + return false; + } + + fdeRecord->length = FIRCLSParseRecordLengthAndAdvance(&ptr); + if (fdeRecord->length == 0) { + FIRCLSSDKLog("Error: FDE has zero length\n"); + return false; + } + + // length does not include length field + const void* endAddress = ptr + fdeRecord->length; + + // According to the spec, this is 32/64 bit value, but libunwind always + // parses this as a 32bit value. + fdeRecord->cieOffset = FIRCLSParseUint32AndAdvance(&ptr); + if (fdeRecord->cieOffset == 0) { + FIRCLSSDKLog("Error: CIE offset invalid\n"); + return false; + } + + if (parseCIE) { + // The CIE offset is really weird. It appears to be an offset from the + // beginning of its field. This isn't what the documentation says, but it is + // a little ambigious. This is what DwarfParser.hpp does. + // Note that we have to back up one sizeof(uint32_t), because we've advanced + // by parsing the offset + const void* ciePointer = ptr - fdeRecord->cieOffset - sizeof(uint32_t); + if (!FIRCLSDwarfParseCIERecord(cieRecord, ciePointer)) { + FIRCLSSDKLog("Error: Unable to parse CIE record\n"); + return false; + } + } + + if (!FIRCLSDwarfCIEIsValid(cieRecord)) { + FIRCLSSDKLog("Error: CIE invalid\n"); + return false; + } + + // the next field depends on the pointer encoding style used + fdeRecord->startAddress = + FIRCLSParseAddressWithEncodingAndAdvance(&ptr, cieRecord->pointerEncoding); + if (fdeRecord->startAddress == CLS_INVALID_ADDRESS) { + FIRCLSSDKLog("Error: Found an invalid start address\n"); + return false; + } + + // Here's something weird too. The range is encoded as a "special" address, where only the value + // is used, regardless of other pointer-encoding schemes. + fdeRecord->rangeSize = FIRCLSParseAddressWithEncodingAndAdvance( + &ptr, cieRecord->pointerEncoding & DW_EH_PE_VALUE_MASK); + if (fdeRecord->rangeSize == CLS_INVALID_ADDRESS) { + FIRCLSSDKLog("Error: Found an invalid address range\n"); + return false; + } + + // Just skip over the section for now. The data here is only needed for personality functions, + // which we don't need + if (FIRCLSDwarfCIEHasAugmentationData(cieRecord)) { + uintptr_t augmentationLength = (uintptr_t)FIRCLSParseULEB128AndAdvance(&ptr); + + ptr += augmentationLength; + } + + fdeRecord->instructions.data = ptr; + fdeRecord->instructions.length = (uint32_t)(endAddress - ptr); + + return true; +} + +bool FIRCLSDwarfParseCFIFromFDERecord(FIRCLSDwarfCFIRecord* record, const void* ptr) { + if (!record || !ptr) { + return false; + } + + return FIRCLSDwarfParseFDERecord(&record->fde, true, &record->cie, ptr); +} + +bool FIRCLSDwarfParseCFIFromFDERecordOffset(FIRCLSDwarfCFIRecord* record, + const void* ehFrame, + uintptr_t fdeOffset) { + if (!record || !ehFrame || (fdeOffset == 0)) { + return false; + } + + const void* ptr = ehFrame + fdeOffset; + + return FIRCLSDwarfParseCFIFromFDERecord(record, ptr); +} + +#pragma mark - Properties +bool FIRCLSDwarfCIEIsValid(DWARFCIERecord* cie) { + if (!cie) { + return false; + } + + if (cie->length == 0) { + return false; + } + + if (cie->version != 1 && cie->version != 3) { + return false; + } + + return true; +} + +bool FIRCLSDwarfCIEHasAugmentationData(DWARFCIERecord* cie) { + if (!cie) { + return false; + } + + if (!cie->augmentation) { + return false; + } + + return cie->augmentation[0] == 'z'; +} + +#pragma mark - Instructions + +static bool FIRCLSDwarfParseAndExecute_set_loc(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + uintptr_t operand = FIRCLSParseAddressWithEncodingAndAdvance(cursor, cieRecord->pointerEncoding); + + *codeOffset = operand; + + FIRCLSDwarfLog("DW_CFA_set_loc %lu\n", operand); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc1(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + int64_t offset = FIRCLSParseUint8AndAdvance(cursor) * cieRecord->codeAlignFactor; + + *codeOffset += offset; + + FIRCLSDwarfLog("DW_CFA_advance_loc1 %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc2(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + int64_t offset = FIRCLSParseUint16AndAdvance(cursor) * cieRecord->codeAlignFactor; + + *codeOffset += offset; + + FIRCLSDwarfLog("DW_CFA_advance_loc2 %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc4(const void** cursor, + DWARFCIERecord* cieRecord, + intptr_t* codeOffset) { + int64_t offset = FIRCLSParseUint32AndAdvance(cursor) * cieRecord->codeAlignFactor; + + *codeOffset += offset; + + FIRCLSDwarfLog("DW_CFA_advance_loc4 %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_def_cfa register number\n"); + return false; + } + + int64_t offset = FIRCLSParseULEB128AndAdvance(cursor); + + state->cfaRegister = regNum; + state->cfaRegisterOffset = offset; + + FIRCLSDwarfLog("DW_CFA_def_cfa %llu, %lld\n", regNum, offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa_register(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_def_cfa_register register number\n"); + return false; + } + + state->cfaRegister = regNum; + + FIRCLSDwarfLog("DW_CFA_def_cfa_register %llu\n", regNum); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa_offset(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t offset = FIRCLSParseULEB128AndAdvance(cursor); + + state->cfaRegisterOffset = offset; + + FIRCLSDwarfLog("DW_CFA_def_cfa_offset %lld\n", offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_same_value(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_same_value register number\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterUnused; + + FIRCLSDwarfLog("DW_CFA_same_value %llu\n", regNum); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_register(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_register number\n"); + return false; + } + + uint64_t regValue = FIRCLSParseULEB128AndAdvance(cursor); + + if (regValue > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_register value\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterInRegister; + state->registers[regNum].value = regValue; + + FIRCLSDwarfLog("DW_CFA_register %llu %llu\n", regNum, regValue); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_expression(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_expression register number\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterAtExpression; + state->registers[regNum].value = (uintptr_t)*cursor; + + // read the length of the expression, and advance past it + uint64_t length = FIRCLSParseULEB128AndAdvance(cursor); + *cursor += length; + + FIRCLSDwarfLog("DW_CFA_expression %llu %llu\n", regNum, length); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_val_expression(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + uint64_t regNum = FIRCLSParseULEB128AndAdvance(cursor); + + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_val_expression register number\n"); + return false; + } + + state->registers[regNum].location = FIRCLSDwarfRegisterIsExpression; + state->registers[regNum].value = (uintptr_t)*cursor; + + // read the length of the expression, and advance past it + uint64_t length = FIRCLSParseULEB128AndAdvance(cursor); + *cursor += length; + + FIRCLSDwarfLog("DW_CFA_val_expression %llu %llu\n", regNum, length); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_def_cfa_expression(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state) { + state->cfaRegister = CLS_DWARF_INVALID_REGISTER_NUM; + state->cfaExpression = *cursor; + + // read the length of the expression, and advance past it + uint64_t length = FIRCLSParseULEB128AndAdvance(cursor); + *cursor += length; + + FIRCLSDwarfLog("DW_CFA_def_cfa_expression %llu\n", length); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_offset(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + uint8_t regNum) { + if (regNum > CLS_DWARF_MAX_REGISTER_NUM) { + FIRCLSSDKLog("Error: Found an invalid DW_CFA_offset register number\n"); + return false; + } + + int64_t offset = FIRCLSParseULEB128AndAdvance(cursor) * cieRecord->dataAlignFactor; + + state->registers[regNum].location = FIRCLSDwarfRegisterInCFA; + state->registers[regNum].value = offset; + + FIRCLSDwarfLog("DW_CFA_offset %u, %lld\n", regNum, offset); + + return true; +} + +static bool FIRCLSDwarfParseAndExecute_advance_loc(const void** cursor, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + uint8_t delta, + intptr_t* codeOffset) { + if (!FIRCLSIsValidPointer(codeOffset) || !FIRCLSIsValidPointer(cieRecord)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + *codeOffset = delta * (intptr_t)cieRecord->codeAlignFactor; + + FIRCLSDwarfLog("DW_CFA_advance_loc %u\n", delta); + + return true; +} + +static bool FIRCLSDwarfParseAndExecuteInstructionWithOperand(const void** cursor, + uint8_t instruction, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + intptr_t* codeOffset) { + uint8_t operand = instruction & DW_CFA_OPERAND_MASK; + bool success = false; + + switch (instruction & DW_CFA_OPCODE_MASK) { + case DW_CFA_offset: + success = FIRCLSDwarfParseAndExecute_offset(cursor, cieRecord, state, operand); + break; + case DW_CFA_advance_loc: + success = + FIRCLSDwarfParseAndExecute_advance_loc(cursor, cieRecord, state, operand, codeOffset); + break; + case DW_CFA_restore: + FIRCLSSDKLog("Error: Unimplemented DWARF instruction with operand 0x%x\n", instruction); + break; + default: + FIRCLSSDKLog("Error: Unrecognized DWARF instruction 0x%x\n", instruction); + break; + } + + return success; +} + +#pragma mark - Expressions +static bool FIRCLSDwarfEvalulateExpression(const void* cursor, + const FIRCLSThreadContext* registers, + intptr_t stackValue, + intptr_t* result) { + FIRCLSDwarfLog("starting at %p with initial value %lx\n", cursor, stackValue); + + if (!FIRCLSIsValidPointer(cursor) || !FIRCLSIsValidPointer(result)) { + FIRCLSSDKLog("Error: inputs invalid\n"); + return false; + } + + FIRCLSDwarfExpressionMachine machine; + + if (!FIRCLSDwarfExpressionMachineInit(&machine, cursor, registers, stackValue)) { + FIRCLSSDKLog("Error: unable to init DWARF expression machine\n"); + return false; + } + + if (!FIRCLSDwarfExpressionMachinePrepareForExecution(&machine)) { + FIRCLSSDKLog("Error: unable to prepare for execution\n"); + return false; + } + + while (!FIRCLSDwarfExpressionMachineIsFinished(&machine)) { + if (!FIRCLSDwarfExpressionMachineExecuteNextOpcode(&machine)) { + FIRCLSSDKLog("Error: failed to execute DWARF machine opcode\n"); + return false; + } + } + + if (!FIRCLSDwarfExpressionMachineGetResult(&machine, result)) { + FIRCLSSDKLog("Error: failed to get DWARF expression result\n"); + return false; + } + + FIRCLSDwarfLog("successfully computed expression result\n"); + + return true; +} + +#pragma mark - Execution +bool FIRCLSDwarfInstructionsEnumerate(DWARFInstructions* instructions, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + intptr_t pcOffset) { + if (!instructions || !cieRecord || !state) { + FIRCLSSDKLog("Error: inputs invalid\n"); + return false; + } + + // This is a little bit of state that can't be put into the state structure, because + // it is possible for instructions to push/pop state that does not affect this value. + intptr_t codeOffset = 0; + + const void* cursor = instructions->data; + const void* endAddress = cursor + instructions->length; + + FIRCLSDwarfLog("Running instructions from %p to %p\n", cursor, endAddress); + + // parse the instructions, as long as: + // - our data pointer is still in range + // - the pc offset is within the range of instructions that apply + + while ((cursor < endAddress) && (codeOffset < pcOffset)) { + uint8_t instruction = FIRCLSParseUint8AndAdvance(&cursor); + bool success = false; + + switch (instruction) { + case DW_CFA_nop: + FIRCLSDwarfLog("DW_CFA_nop\n"); + continue; + case DW_CFA_set_loc: + success = FIRCLSDwarfParseAndExecute_set_loc(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_advance_loc1: + success = FIRCLSDwarfParseAndExecute_advance_loc1(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_advance_loc2: + success = FIRCLSDwarfParseAndExecute_advance_loc2(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_advance_loc4: + success = FIRCLSDwarfParseAndExecute_advance_loc4(&cursor, cieRecord, &codeOffset); + break; + case DW_CFA_def_cfa: + success = FIRCLSDwarfParseAndExecute_def_cfa(&cursor, cieRecord, state); + break; + case DW_CFA_def_cfa_register: + success = FIRCLSDwarfParseAndExecute_def_cfa_register(&cursor, cieRecord, state); + break; + case DW_CFA_def_cfa_offset: + success = FIRCLSDwarfParseAndExecute_def_cfa_offset(&cursor, cieRecord, state); + break; + case DW_CFA_same_value: + success = FIRCLSDwarfParseAndExecute_same_value(&cursor, cieRecord, state); + break; + case DW_CFA_register: + success = FIRCLSDwarfParseAndExecute_register(&cursor, cieRecord, state); + break; + case DW_CFA_def_cfa_expression: + success = FIRCLSDwarfParseAndExecute_def_cfa_expression(&cursor, cieRecord, state); + break; + case DW_CFA_expression: + success = FIRCLSDwarfParseAndExecute_expression(&cursor, cieRecord, state); + break; + case DW_CFA_val_expression: + success = FIRCLSDwarfParseAndExecute_val_expression(&cursor, cieRecord, state); + break; + case DW_CFA_offset_extended: + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_remember_state: + case DW_CFA_restore_state: + case DW_CFA_offset_extended_sf: + case DW_CFA_def_cfa_sf: + case DW_CFA_def_cfa_offset_sf: + case DW_CFA_val_offset: + case DW_CFA_val_offset_sf: + case DW_CFA_GNU_window_save: + case DW_CFA_GNU_args_size: + case DW_CFA_GNU_negative_offset_extended: + FIRCLSSDKLog("Error: Unimplemented DWARF instruction 0x%x\n", instruction); + return false; + default: + success = FIRCLSDwarfParseAndExecuteInstructionWithOperand(&cursor, instruction, cieRecord, + state, &codeOffset); + break; + } + + if (!success) { + FIRCLSSDKLog("Error: Failed to execute dwarf instruction 0x%x\n", instruction); + return false; + } + } + + return true; +} + +bool FIRCLSDwarfUnwindComputeRegisters(FIRCLSDwarfCFIRecord* record, + FIRCLSThreadContext* registers) { + if (!record || !registers) { + return false; + } + + // We need to run the dwarf instructions to compute our register values. + // - initialize state + // - run the CIE instructions + // - run the FDE instructions + // - grab the values + + FIRCLSDwarfState state; + + memset(&state, 0, sizeof(FIRCLSDwarfState)); + + // We need to run all the instructions in the CIE record. So, pass in a large value for the pc + // offset so we don't stop early. + if (!FIRCLSDwarfInstructionsEnumerate(&record->cie.instructions, &record->cie, &state, + INTPTR_MAX)) { + FIRCLSSDKLog("Error: Unable to run CIE instructions\n"); + return false; + } + + intptr_t pcOffset = FIRCLSThreadContextGetPC(registers) - record->fde.startAddress; + if (pcOffset < 0) { + FIRCLSSDKLog("Error: The FDE pcOffset value cannot be negative\n"); + return false; + } + + if (!FIRCLSDwarfInstructionsEnumerate(&record->fde.instructions, &record->cie, &state, + pcOffset)) { + FIRCLSSDKLog("Error: Unable to run FDE instructions\n"); + return false; + } + + uintptr_t cfaRegister = 0; + + if (!FIRCLSDwarfGetCFA(&state, registers, &cfaRegister)) { + FIRCLSSDKLog("Error: failed to get CFA\n"); + return false; + } + + if (!FIRCLSDwarfUnwindAssignRegisters(&state, registers, cfaRegister, registers)) { + FIRCLSSDKLogError("Error: Unable to assign DWARF registers\n"); + return false; + } + + return true; +} + +bool FIRCLSDwarfUnwindAssignRegisters(const FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSThreadContext* outputRegisters) { + if (!FIRCLSIsValidPointer(state) || !FIRCLSIsValidPointer(registers)) { + FIRCLSSDKLogError("Error: input invalid\n"); + return false; + } + + // make a copy, which we'll be changing + FIRCLSThreadContext newThreadState = *registers; + + // loop through all the registers, so we can set their values + for (size_t i = 0; i <= CLS_DWARF_MAX_REGISTER_NUM; ++i) { + if (state->registers[i].location == FIRCLSDwarfRegisterUnused) { + continue; + } + + const uintptr_t value = + FIRCLSDwarfGetSavedRegister(registers, cfaRegister, state->registers[i]); + + if (!FIRCLSDwarfUnwindSetRegisterValue(&newThreadState, i, value)) { + FIRCLSSDKLog("Error: Unable to restore register value\n"); + return false; + } + } + + if (!FIRCLSDwarfUnwindSetRegisterValue(&newThreadState, CLS_DWARF_REG_SP, cfaRegister)) { + FIRCLSSDKLog("Error: Unable to restore SP value\n"); + return false; + } + + // sanity-check that things have changed + if (FIRCLSDwarfCompareRegisters(registers, &newThreadState, CLS_DWARF_REG_SP)) { + FIRCLSSDKLog("Error: Stack pointer hasn't changed\n"); + return false; + } + + if (FIRCLSDwarfCompareRegisters(registers, &newThreadState, CLS_DWARF_REG_RETURN)) { + FIRCLSSDKLog("Error: PC hasn't changed\n"); + return false; + } + + // set our new value + *outputRegisters = newThreadState; + + return true; +} + +#pragma mark - Register Operations +bool FIRCLSDwarfCompareRegisters(const FIRCLSThreadContext* a, + const FIRCLSThreadContext* b, + uint64_t registerNum) { + return FIRCLSDwarfUnwindGetRegisterValue(a, registerNum) == + FIRCLSDwarfUnwindGetRegisterValue(b, registerNum); +} + +bool FIRCLSDwarfGetCFA(FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t* cfa) { + if (!FIRCLSIsValidPointer(state) || !FIRCLSIsValidPointer(registers) || + !FIRCLSIsValidPointer(cfa)) { + FIRCLSSDKLog("Error: invalid input\n"); + return false; + } + + if (state->cfaExpression) { + if (!FIRCLSDwarfEvalulateExpression(state->cfaExpression, registers, 0, (intptr_t*)cfa)) { + FIRCLSSDKLog("Error: failed to compute CFA expression\n"); + return false; + } + + return true; + } + + // libunwind checks that cfaRegister is not zero. This seems like a potential bug - why couldn't + // it be zero? + + *cfa = FIRCLSDwarfUnwindGetRegisterValue(registers, state->cfaRegister) + + (uintptr_t)state->cfaRegisterOffset; + + return true; +} + +uintptr_t FIRCLSDwarfGetSavedRegister(const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSDwarfRegister dRegister) { + intptr_t result = 0; + + FIRCLSDwarfLog("Getting register %x\n", dRegister.location); + + switch (dRegister.location) { + case FIRCLSDwarfRegisterInCFA: { + const uintptr_t address = cfaRegister + (uintptr_t)dRegister.value; + + if (!FIRCLSReadMemory(address, &result, sizeof(result))) { + FIRCLSSDKLog("Error: Unable to read CFA value\n"); + return 0; + } + } + return result; + case FIRCLSDwarfRegisterInRegister: + return FIRCLSDwarfUnwindGetRegisterValue(registers, dRegister.value); + case FIRCLSDwarfRegisterOffsetFromCFA: + FIRCLSSDKLog("Error: OffsetFromCFA unhandled\n"); + break; + case FIRCLSDwarfRegisterAtExpression: + if (!FIRCLSDwarfEvalulateExpression((void*)dRegister.value, registers, cfaRegister, + &result)) { + FIRCLSSDKLog("Error: unable to evaluate expression\n"); + return 0; + } + + if (!FIRCLSReadMemory(result, &result, sizeof(result))) { + FIRCLSSDKLog("Error: Unable to read memory computed from expression\n"); + return 0; + } + + return result; + case FIRCLSDwarfRegisterIsExpression: + if (!FIRCLSDwarfEvalulateExpression((void*)dRegister.value, registers, cfaRegister, + &result)) { + FIRCLSSDKLog("Error: unable to evaluate expression\n"); + return 0; + } + + return result; + default: + FIRCLSSDKLog("Error: Unrecognized register save location 0x%x\n", dRegister.location); + break; + } + + return 0; +} + +#if DEBUG +#pragma mark - Debugging +void FIRCLSCFIRecordShow(FIRCLSDwarfCFIRecord* record) { + if (!record) { + FIRCLSSDKLog("Error: CFI record: null\n"); + return; + } + + FIRCLSCIERecordShow(&record->cie); + FIRCLSFDERecordShow(&record->fde, &record->cie); +} + +void FIRCLSCIERecordShow(DWARFCIERecord* record) { + if (!record) { + FIRCLSSDKLog("Error: CIE: null\n"); + return; + } + + FIRCLSSDKLog("CIE:\n"); + FIRCLSSDKLog(" length: %llu\n", record->length); + FIRCLSSDKLog(" version: %u\n", record->version); + FIRCLSSDKLog(" augmentation: %s\n", record->augmentation); + FIRCLSSDKLog(" EH Data: 0x%04lx\n", record->ehData); + FIRCLSSDKLog("LSDA encoding: 0x%02x\n", record->lsdaEncoding); + FIRCLSSDKLog(" personality: 0x%lx\n", record->personalityFunction); + + FIRCLSDwarfPointerEncodingShow(" encoding", record->pointerEncoding); + FIRCLSDwarfPointerEncodingShow(" P encoding", record->personalityEncoding); + + FIRCLSSDKLog(" code align: %llu\n", record->codeAlignFactor); + FIRCLSSDKLog(" data align: %lld\n", record->dataAlignFactor); + FIRCLSSDKLog(" RA register: %llu\n", record->returnAddressRegister); + + FIRCLSDwarfInstructionsShow(&record->instructions, record); +} + +void FIRCLSFDERecordShow(DWARFFDERecord* record, DWARFCIERecord* cie) { + if (!record) { + FIRCLSSDKLog("FDE: null\n"); + return; + } + + FIRCLSSDKLog("FDE:\n"); + FIRCLSSDKLog(" length: %llu\n", record->length); + FIRCLSSDKLog(" CIE offset: %llu\n", record->cieOffset); + FIRCLSSDKLog(" start addr: 0x%lx\n", record->startAddress); + FIRCLSSDKLog(" range: %lu\n", record->rangeSize); + + FIRCLSDwarfInstructionsShow(&record->instructions, cie); +} + +void FIRCLSDwarfPointerEncodingShow(const char* leadString, uint8_t encoding) { + if (encoding == DW_EH_PE_omit) { + FIRCLSSDKLog("%s: 0x%02x (omit)\n", leadString, encoding); + } else { + const char* peValue = ""; + const char* peOffset = ""; + + switch (encoding & DW_EH_PE_VALUE_MASK) { + case DW_EH_PE_absptr: + peValue = "DW_EH_PE_absptr"; + break; + case DW_EH_PE_uleb128: + peValue = "DW_EH_PE_uleb128"; + break; + case DW_EH_PE_udata2: + peValue = "DW_EH_PE_udata2"; + break; + case DW_EH_PE_udata4: + peValue = "DW_EH_PE_udata4"; + break; + case DW_EH_PE_udata8: + peValue = "DW_EH_PE_udata8"; + break; + case DW_EH_PE_signed: + peValue = "DW_EH_PE_signed"; + break; + case DW_EH_PE_sleb128: + peValue = "DW_EH_PE_sleb128"; + break; + case DW_EH_PE_sdata2: + peValue = "DW_EH_PE_sdata2"; + break; + case DW_EH_PE_sdata4: + peValue = "DW_EH_PE_sdata4"; + break; + case DW_EH_PE_sdata8: + peValue = "DW_EH_PE_sdata8"; + break; + default: + peValue = "unknown"; + break; + } + + switch (encoding & DW_EH_PE_RELATIVE_OFFSET_MASK) { + case DW_EH_PE_absptr: + break; + case DW_EH_PE_pcrel: + peOffset = " + DW_EH_PE_pcrel"; + break; + case DW_EH_PE_textrel: + peOffset = " + DW_EH_PE_textrel"; + break; + case DW_EH_PE_datarel: + peOffset = " + DW_EH_PE_datarel"; + break; + case DW_EH_PE_funcrel: + peOffset = " + DW_EH_PE_funcrel"; + break; + case DW_EH_PE_aligned: + peOffset = " + DW_EH_PE_aligned"; + break; + case DW_EH_PE_indirect: + peOffset = " + DW_EH_PE_indirect"; + break; + default: + break; + } + + FIRCLSSDKLog("%s: 0x%02x (%s%s)\n", leadString, encoding, peValue, peOffset); + } +} + +void FIRCLSDwarfInstructionsShow(DWARFInstructions* instructions, DWARFCIERecord* cie) { + if (!instructions) { + FIRCLSSDKLog("Error: Instructions null\n"); + } + + FIRCLSDwarfState state; + + memset(&state, 0, sizeof(FIRCLSDwarfState)); + + FIRCLSDwarfInstructionsEnumerate(instructions, cie, &state, -1); +} + +#endif + +#else +INJECT_STRIP_SYMBOL(dwarf_unwind) +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h new file mode 100644 index 00000000..dca84a0c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h @@ -0,0 +1,138 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h" + +#if CLS_DWARF_UNWINDING_SUPPORTED + +#pragma mark Structures +typedef struct { + uint32_t length; + const void* data; +} DWARFInstructions; + +typedef struct { + uint64_t length; + uint8_t version; + uintptr_t ehData; // 8 bytes for 64-bit architectures, 4 bytes for 32 + const char* augmentation; + uint8_t pointerEncoding; + uint8_t lsdaEncoding; + uint8_t personalityEncoding; + uintptr_t personalityFunction; + uint64_t codeAlignFactor; + int64_t dataAlignFactor; + uint64_t returnAddressRegister; // is 64 bits enough for this value? + bool signalFrame; + + DWARFInstructions instructions; +} DWARFCIERecord; + +typedef struct { + uint64_t length; + uint64_t cieOffset; // also an arch-specific size + uintptr_t startAddress; + uintptr_t rangeSize; + + DWARFInstructions instructions; +} DWARFFDERecord; + +typedef struct { + DWARFCIERecord cie; + DWARFFDERecord fde; +} FIRCLSDwarfCFIRecord; + +typedef enum { + FIRCLSDwarfRegisterUnused = 0, + FIRCLSDwarfRegisterInCFA, + FIRCLSDwarfRegisterOffsetFromCFA, + FIRCLSDwarfRegisterInRegister, + FIRCLSDwarfRegisterAtExpression, + FIRCLSDwarfRegisterIsExpression +} FIRCLSDwarfRegisterLocation; + +typedef struct { + FIRCLSDwarfRegisterLocation location; + uint64_t value; +} FIRCLSDwarfRegister; + +typedef struct { + uint64_t cfaRegister; + int64_t cfaRegisterOffset; + const void* cfaExpression; + uint32_t spArgSize; + + FIRCLSDwarfRegister registers[CLS_DWARF_MAX_REGISTER_NUM + 1]; +} FIRCLSDwarfState; + +__BEGIN_DECLS + +#pragma mark - Parsing +bool FIRCLSDwarfParseCIERecord(DWARFCIERecord* cie, const void* ptr); +bool FIRCLSDwarfParseFDERecord(DWARFFDERecord* fdeRecord, + bool parseCIE, + DWARFCIERecord* cieRecord, + const void* ptr); +bool FIRCLSDwarfParseCFIFromFDERecord(FIRCLSDwarfCFIRecord* record, const void* ptr); +bool FIRCLSDwarfParseCFIFromFDERecordOffset(FIRCLSDwarfCFIRecord* record, + const void* ehFrame, + uintptr_t fdeOffset); + +#pragma mark - Properties +bool FIRCLSDwarfCIEIsValid(DWARFCIERecord* cie); +bool FIRCLSDwarfCIEHasAugmentationData(DWARFCIERecord* cie); + +#pragma mark - Execution +bool FIRCLSDwarfInstructionsEnumerate(DWARFInstructions* instructions, + DWARFCIERecord* cieRecord, + FIRCLSDwarfState* state, + intptr_t pcOffset); +bool FIRCLSDwarfUnwindComputeRegisters(FIRCLSDwarfCFIRecord* record, + FIRCLSThreadContext* registers); +bool FIRCLSDwarfUnwindAssignRegisters(const FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSThreadContext* outputRegisters); + +#pragma mark - Register Operations +bool FIRCLSDwarfCompareRegisters(const FIRCLSThreadContext* a, + const FIRCLSThreadContext* b, + uint64_t registerNum); + +bool FIRCLSDwarfGetCFA(FIRCLSDwarfState* state, + const FIRCLSThreadContext* registers, + uintptr_t* cfa); +uintptr_t FIRCLSDwarfGetSavedRegister(const FIRCLSThreadContext* registers, + uintptr_t cfaRegister, + FIRCLSDwarfRegister dRegister); + +#if DEBUG +#pragma mark - Debugging +void FIRCLSCFIRecordShow(FIRCLSDwarfCFIRecord* record); +void FIRCLSCIERecordShow(DWARFCIERecord* record); +void FIRCLSFDERecordShow(DWARFFDERecord* record, DWARFCIERecord* cie); +void FIRCLSDwarfPointerEncodingShow(const char* leadString, uint8_t encoding); +void FIRCLSDwarfInstructionsShow(DWARFInstructions* instructions, DWARFCIERecord* cie); +#endif + +__END_DECLS + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h new file mode 100644 index 00000000..7e015cf4 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h @@ -0,0 +1,152 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <stdint.h> + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" + +#if CLS_CPU_X86_64 +enum { + CLS_DWARF_X86_64_RAX = 0, + CLS_DWARF_X86_64_RDX = 1, + CLS_DWARF_X86_64_RCX = 2, + CLS_DWARF_X86_64_RBX = 3, + CLS_DWARF_X86_64_RSI = 4, + CLS_DWARF_X86_64_RDI = 5, + CLS_DWARF_X86_64_RBP = 6, + CLS_DWARF_X86_64_RSP = 7, + CLS_DWARF_X86_64_R8 = 8, + CLS_DWARF_X86_64_R9 = 9, + CLS_DWARF_X86_64_R10 = 10, + CLS_DWARF_X86_64_R11 = 11, + CLS_DWARF_X86_64_R12 = 12, + CLS_DWARF_X86_64_R13 = 13, + CLS_DWARF_X86_64_R14 = 14, + CLS_DWARF_X86_64_R15 = 15, + + CLS_DWARF_X86_64_RET_ADDR = 16 +}; + +#define CLS_DWARF_REG_RETURN CLS_DWARF_X86_64_RET_ADDR +#define CLS_DWARF_REG_SP CLS_DWARF_X86_64_RSP +#define CLS_DWARF_REG_FP CLS_DWARF_X86_64_RBP + +#define CLS_DWARF_MAX_REGISTER_NUM (CLS_DWARF_X86_64_RET_ADDR) + +#elif CLS_CPU_I386 + +enum { + CLS_DWARF_X86_EAX = 0, + CLS_DWARF_X86_ECX = 1, + CLS_DWARF_X86_EDX = 2, + CLS_DWARF_X86_EBX = 3, + CLS_DWARF_X86_EBP = 4, + CLS_DWARF_X86_ESP = 5, + CLS_DWARF_X86_ESI = 6, + CLS_DWARF_X86_EDI = 7, + + CLS_DWARF_X86_RET_ADDR = 8 +}; + +#define CLS_DWARF_REG_RETURN CLS_DWARF_X86_RET_ADDR +#define CLS_DWARF_REG_SP CLS_DWARF_X86_ESP +#define CLS_DWARF_REG_FP CLS_DWARF_X86_EBP + +#define CLS_DWARF_MAX_REGISTER_NUM (CLS_DWARF_X86_RET_ADDR) + +#elif CLS_CPU_ARM64 + +// 64-bit ARM64 registers +enum { + CLS_DWARF_ARM64_X0 = 0, + CLS_DWARF_ARM64_X1 = 1, + CLS_DWARF_ARM64_X2 = 2, + CLS_DWARF_ARM64_X3 = 3, + CLS_DWARF_ARM64_X4 = 4, + CLS_DWARF_ARM64_X5 = 5, + CLS_DWARF_ARM64_X6 = 6, + CLS_DWARF_ARM64_X7 = 7, + CLS_DWARF_ARM64_X8 = 8, + CLS_DWARF_ARM64_X9 = 9, + CLS_DWARF_ARM64_X10 = 10, + CLS_DWARF_ARM64_X11 = 11, + CLS_DWARF_ARM64_X12 = 12, + CLS_DWARF_ARM64_X13 = 13, + CLS_DWARF_ARM64_X14 = 14, + CLS_DWARF_ARM64_X15 = 15, + CLS_DWARF_ARM64_X16 = 16, + CLS_DWARF_ARM64_X17 = 17, + CLS_DWARF_ARM64_X18 = 18, + CLS_DWARF_ARM64_X19 = 19, + CLS_DWARF_ARM64_X20 = 20, + CLS_DWARF_ARM64_X21 = 21, + CLS_DWARF_ARM64_X22 = 22, + CLS_DWARF_ARM64_X23 = 23, + CLS_DWARF_ARM64_X24 = 24, + CLS_DWARF_ARM64_X25 = 25, + CLS_DWARF_ARM64_X26 = 26, + CLS_DWARF_ARM64_X27 = 27, + CLS_DWARF_ARM64_X28 = 28, + CLS_DWARF_ARM64_X29 = 29, + CLS_DWARF_ARM64_FP = 29, + CLS_DWARF_ARM64_X30 = 30, + CLS_DWARF_ARM64_LR = 30, + CLS_DWARF_ARM64_X31 = 31, + CLS_DWARF_ARM64_SP = 31, + // reserved block + CLS_DWARF_ARM64_D0 = 64, + CLS_DWARF_ARM64_D1 = 65, + CLS_DWARF_ARM64_D2 = 66, + CLS_DWARF_ARM64_D3 = 67, + CLS_DWARF_ARM64_D4 = 68, + CLS_DWARF_ARM64_D5 = 69, + CLS_DWARF_ARM64_D6 = 70, + CLS_DWARF_ARM64_D7 = 71, + CLS_DWARF_ARM64_D8 = 72, + CLS_DWARF_ARM64_D9 = 73, + CLS_DWARF_ARM64_D10 = 74, + CLS_DWARF_ARM64_D11 = 75, + CLS_DWARF_ARM64_D12 = 76, + CLS_DWARF_ARM64_D13 = 77, + CLS_DWARF_ARM64_D14 = 78, + CLS_DWARF_ARM64_D15 = 79, + CLS_DWARF_ARM64_D16 = 80, + CLS_DWARF_ARM64_D17 = 81, + CLS_DWARF_ARM64_D18 = 82, + CLS_DWARF_ARM64_D19 = 83, + CLS_DWARF_ARM64_D20 = 84, + CLS_DWARF_ARM64_D21 = 85, + CLS_DWARF_ARM64_D22 = 86, + CLS_DWARF_ARM64_D23 = 87, + CLS_DWARF_ARM64_D24 = 88, + CLS_DWARF_ARM64_D25 = 89, + CLS_DWARF_ARM64_D26 = 90, + CLS_DWARF_ARM64_D27 = 91, + CLS_DWARF_ARM64_D28 = 92, + CLS_DWARF_ARM64_D29 = 93, + CLS_DWARF_ARM64_D30 = 94, + CLS_DWARF_ARM64_D31 = 95 +}; + +#define CLS_DWARF_MAX_REGISTER_NUM (CLS_DWARF_ARM64_SP) + +#define CLS_DWARF_REG_RETURN CLS_DWARF_ARM64_LR +#define CLS_DWARF_REG_SP CLS_DWARF_ARM64_SP +#define CLS_DWARF_REG_FP CLS_DWARF_ARM64_FP + +#endif + +#define CLS_DWARF_INVALID_REGISTER_NUM (CLS_DWARF_MAX_REGISTER_NUM + 1) diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.c new file mode 100644 index 00000000..f0819189 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.c @@ -0,0 +1,319 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSBinaryImage.h" +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Components/FIRCLSGlobals.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#include <mach/mach.h> +#include <signal.h> +#include <stdio.h> + +// Without a limit on the number of frames we unwind, there's a real possibility +// we'll get stuck in an infinite loop. But, we still need pretty big limits, +// because stacks can get quite big. Also, the stacks are different on the platforms. +// These values were empirically determined (~525000 on OS X, ~65000 on iOS). +#if TARGET_OS_EMBEDDED +const uint32_t FIRCLSUnwindMaxFrames = 100000; +#else +const uint32_t FIRCLSUnwindMaxFrames = 600000; +#endif + +const uint32_t FIRCLSUnwindInfiniteRecursionCountThreshold = 10; + +#pragma mark Prototypes +static bool FIRCLSUnwindNextFrameUsingAllStrategies(FIRCLSUnwindContext* context); +#if CLS_COMPACT_UNWINDING_SUPPORTED +static bool FIRCLSUnwindWithCompactUnwindInfo(FIRCLSUnwindContext* context); +#endif +bool FIRCLSUnwindContextHasValidPCAndSP(FIRCLSUnwindContext* context); + +#pragma mark - API +bool FIRCLSUnwindInit(FIRCLSUnwindContext* context, FIRCLSThreadContext threadContext) { + if (!context) { + return false; + } + + memset(context, 0, sizeof(FIRCLSUnwindContext)); + + context->registers = threadContext; + + return true; +} + +bool FIRCLSUnwindNextFrame(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + if (!FIRCLSUnwindContextHasValidPCAndSP(context)) { + // This is a special-case. It is possible to try to unwind a thread that has no stack (ie, is + // executing zero functions. I believe this happens when a thread has exited, but before the + // kernel has actually cleaned it up. This situation can only apply to the first frame. So, in + // that case, we don't count it as an error. But, if it happens mid-unwind, it's a problem. + + if (context->frameCount == 0) { + FIRCLSSDKLog("Cancelling unwind for thread with invalid PC/SP\n"); + } else { + FIRCLSSDKLog("Error: thread PC/SP invalid before unwind\n"); + } + + return false; + } + + if (!FIRCLSUnwindNextFrameUsingAllStrategies(context)) { + FIRCLSSDKLogError("Failed to advance to the next frame\n"); + return false; + } + + uintptr_t pc = FIRCLSUnwindGetPC(context); + uintptr_t sp = FIRCLSUnwindGetStackPointer(context); + + // Unwinding will complete when this is no longer a valid value + if (!FIRCLSIsValidPointer(pc)) { + return false; + } + + // after unwinding, validate that we have a sane register value + if (!FIRCLSIsValidPointer(sp)) { + FIRCLSSDKLog("Error: SP (%p) isn't a valid pointer\n", (void*)sp); + return false; + } + + // track repeating frames + if (context->lastFramePC == pc) { + context->repeatCount += 1; + } else { + context->repeatCount = 0; + } + + context->frameCount += 1; + context->lastFramePC = pc; + + return true; +} + +#pragma mark - Register Accessors +uintptr_t FIRCLSUnwindGetPC(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return FIRCLSThreadContextGetPC(&context->registers); +} + +uintptr_t FIRCLSUnwindGetStackPointer(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return FIRCLSThreadContextGetStackPointer(&context->registers); +} + +static uintptr_t FIRCLSUnwindGetFramePointer(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return FIRCLSThreadContextGetFramePointer(&context->registers); +} + +uint32_t FIRCLSUnwindGetFrameRepeatCount(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + return 0; + } + + return context->repeatCount; +} + +#pragma mark - Unwind Strategies +static bool FIRCLSUnwindNextFrameUsingAllStrategies(FIRCLSUnwindContext* context) { + if (!FIRCLSIsValidPointer(context)) { + FIRCLSSDKLogError("Arguments invalid\n"); + return false; + } + + if (context->frameCount >= FIRCLSUnwindMaxFrames) { + FIRCLSSDKLogWarn("Exceeded maximum number of frames\n"); + return false; + } + + uintptr_t pc = FIRCLSUnwindGetPC(context); + + // Ok, what's going on here? libunwind's UnwindCursor<A,R>::setInfoBasedOnIPRegister has a + // parameter that, if true, does this subtraction. Despite the comments in the code + // (of 35.1), I found that the parameter was almost always set to true. + // + // I then ran into a problem when unwinding from _pthread_start -> thread_start. This + // is a common transition, which happens in pretty much every report. An extra frame + // was being generated, because the PC we get for _pthread_start was mapping to exactly + // one greater than the function's last byte, according to the compact unwind info. This + // resulted in using the wrong compact encoding, and picking the next function, which + // turned out to be dwarf instead of a frame pointer. + + // So, the moral is - do the subtraction for all frames except the first. I haven't found + // a case where it produces an incorrect result. Also note that at first, I thought this would + // subtract one from the final addresses too. But, the end of this function will *compute* PC, + // so this value is used only to look up unwinding data. + + if (context->frameCount > 0) { + --pc; + if (!FIRCLSThreadContextSetPC(&context->registers, pc)) { + FIRCLSSDKLogError("Unable to set PC\n"); + return false; + } + } + + if (!FIRCLSIsValidPointer(pc)) { + FIRCLSSDKLogError("PC is invalid\n"); + return false; + } + + // the first frame is special - as the registers we need + // are already loaded by definition + if (context->frameCount == 0) { + return true; + } + +#if CLS_COMPACT_UNWINDING_SUPPORTED + // attempt to advance to the next frame using compact unwinding, and + // only fall back to the frame pointer if that fails + if (FIRCLSUnwindWithCompactUnwindInfo(context)) { + return true; + } +#endif + + // If the frame pointer is zero, we cannot use an FP-based unwind and we can reasonably + // assume that we've just gotten to the end of the stack. + if (FIRCLSUnwindGetFramePointer(context) == 0) { + FIRCLSSDKLogWarn("FP is zero, aborting unwind\n"); + // make sure to set the PC to zero, to indicate the unwind is complete + return FIRCLSThreadContextSetPC(&context->registers, 0); + } + + // Only allow stack scanning (as a last resort) if we're on the first frame. All others + // are too likely to screw up. + if (FIRCLSUnwindWithFramePointer(&context->registers, context->frameCount == 1)) { + return true; + } + + FIRCLSSDKLogError("Unable to use frame pointer\n"); + + return false; +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED +static bool FIRCLSUnwindWithCompactUnwindInfo(FIRCLSUnwindContext* context) { + if (!context) { + return false; + } + + // step one - find the image the current pc is within + FIRCLSBinaryImageRuntimeNode image; + + uintptr_t pc = FIRCLSUnwindGetPC(context); + + if (!FIRCLSBinaryImageSafeFindImageForAddress(pc, &image)) { + FIRCLSSDKLogWarn("Unable to find binary for %p\n", (void*)pc); + return false; + } + +#if CLS_BINARY_IMAGE_RUNTIME_NODE_RECORD_NAME + FIRCLSSDKLogDebug("Binary image for %p at %p => %s\n", (void*)pc, image.baseAddress, image.name); +#else + FIRCLSSDKLogDebug("Binary image for %p at %p\n", (void*)pc, image.baseAddress); +#endif + + if (!FIRCLSBinaryImageSafeHasUnwindInfo(&image)) { + FIRCLSSDKLogInfo("Binary image at %p has no unwind info\n", image.baseAddress); + return false; + } + + if (!FIRCLSCompactUnwindInit(&context->compactUnwindState, image.unwindInfo, image.ehFrame, + (uintptr_t)image.baseAddress)) { + FIRCLSSDKLogError("Unable to read unwind info\n"); + return false; + } + + // this function will actually attempt to find compact unwind info for the current PC, + // and use it to mutate the context register state + return FIRCLSCompactUnwindLookupAndCompute(&context->compactUnwindState, &context->registers); +} +#endif + +#pragma mark - Utility Functions +bool FIRCLSUnwindContextHasValidPCAndSP(FIRCLSUnwindContext* context) { + return FIRCLSIsValidPointer(FIRCLSUnwindGetPC(context)) && + FIRCLSIsValidPointer(FIRCLSUnwindGetStackPointer(context)); +} + +#if CLS_CPU_64BIT +#define BASIC_INFO_TYPE vm_region_basic_info_64_t +#define BASIC_INFO VM_REGION_BASIC_INFO_64 +#define BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT_64 +#define vm_region_query_fn vm_region_64 +#else +#define BASIC_INFO_TYPE vm_region_basic_info_t +#define BASIC_INFO VM_REGION_BASIC_INFO +#define BASIC_INFO_COUNT VM_REGION_BASIC_INFO_COUNT +#define vm_region_query_fn vm_region +#endif +bool FIRCLSUnwindIsAddressExecutable(vm_address_t address) { +#if CLS_COMPACT_UNWINDING_SUPPORTED + FIRCLSBinaryImageRuntimeNode unusedNode; + + return FIRCLSBinaryImageSafeFindImageForAddress(address, &unusedNode); +#else + return true; +#endif +} + +bool FIRCLSUnwindFirstExecutableAddress(vm_address_t start, + vm_address_t end, + vm_address_t* foundAddress) { + // This function walks up the data on the stack, looking for the first value that is an address on + // an exectuable page. This is a heurestic, and can hit false positives. + + *foundAddress = 0; // write in a 0 + + do { + vm_address_t address; + + FIRCLSSDKLogDebug("Checking address %p => %p\n", (void*)start, (void*)*(uintptr_t*)start); + + // if start isn't a valid pointer, don't even bother trying + if (FIRCLSIsValidPointer(start)) { + if (!FIRCLSReadMemory(start, &address, sizeof(void*))) { + // if we fail to read from the stack, we're done + return false; + } + + FIRCLSSDKLogDebug("Checking for executable %p\n", (void*)address); + // when we find an exectuable address, we're finished + if (FIRCLSUnwindIsAddressExecutable(address)) { + *foundAddress = address; + return true; + } + } + + start += sizeof(void*); // move back up the stack + + } while (start < end); + + return false; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h new file mode 100644 index 00000000..cbf46f90 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h @@ -0,0 +1,53 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" +#if CLS_COMPACT_UNWINDING_SUPPORTED +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h" +#endif +#include <mach/vm_types.h> +#include <stdbool.h> + +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h" + +extern const uint32_t FIRCLSUnwindMaxFrames; + +extern const uint32_t FIRCLSUnwindInfiniteRecursionCountThreshold; + +typedef struct { + FIRCLSThreadContext registers; + uint32_t frameCount; +#if CLS_COMPACT_UNWINDING_SUPPORTED + FIRCLSCompactUnwindContext compactUnwindState; +#endif + uintptr_t lastFramePC; + uint32_t repeatCount; +} FIRCLSUnwindContext; + +// API +bool FIRCLSUnwindInit(FIRCLSUnwindContext* context, FIRCLSThreadContext threadContext); + +bool FIRCLSUnwindNextFrame(FIRCLSUnwindContext* context); +uintptr_t FIRCLSUnwindGetPC(FIRCLSUnwindContext* context); +uintptr_t FIRCLSUnwindGetStackPointer(FIRCLSUnwindContext* context); +uint32_t FIRCLSUnwindGetFrameRepeatCount(FIRCLSUnwindContext* context); + +// utility functions +bool FIRCLSUnwindIsAddressExecutable(vm_address_t address); +bool FIRCLSUnwindFirstExecutableAddress(vm_address_t start, + vm_address_t end, + vm_address_t* foundAddress); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h new file mode 100644 index 00000000..714a7aed --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSThreadState.h" +#if CLS_COMPACT_UNWINDING_SUPPORTED +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h" +#endif + +bool FIRCLSUnwindWithFramePointer(FIRCLSThreadContext *registers, bool allowScanning); +uintptr_t FIRCLSUnwindStackPointerFromFramePointer(uintptr_t framePtr); + +#if CLS_DWARF_UNWINDING_SUPPORTED +uintptr_t FIRCLSCompactUnwindDwarfOffset(compact_unwind_encoding_t encoding); +bool FIRCLSDwarfUnwindSetRegisterValue(FIRCLSThreadContext *registers, + uint64_t num, + uintptr_t value); +uintptr_t FIRCLSDwarfUnwindGetRegisterValue(const FIRCLSThreadContext *registers, uint64_t num); +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arm.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arm.c new file mode 100644 index 00000000..dab6336a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arm.c @@ -0,0 +1,313 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h" +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#if CLS_CPU_ARM || CLS_CPU_ARM64 + +static bool FIRCLSUnwindWithLRRegister(FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(registers)) { + return false; + } + + // Return address is in LR, SP is pointing to the next frame. + uintptr_t value = FIRCLSThreadContextGetLinkRegister(registers); + + if (!FIRCLSIsValidPointer(value)) { + FIRCLSSDKLog("Error: LR value is invalid\n"); + return false; + } + + return FIRCLSThreadContextSetPC(registers, value); +} + +bool FIRCLSUnwindWithFramePointer(FIRCLSThreadContext* registers, bool allowScanning) { + if (allowScanning) { + // The LR register does have the return address here, but there are situations where + // this can produce false matches. Better backend rules can fix this up in many cases. + if (FIRCLSUnwindWithLRRegister(registers)) { + return true; + } else { + // In this case, we're unable to use the LR. We don't want to just stop unwinding, so + // proceed with the normal, non-scanning path + FIRCLSSDKLog("Unable to use LR, skipping\n"); + } + } + + // read the values from the stack + const uintptr_t framePointer = FIRCLSThreadContextGetFramePointer(registers); + uintptr_t stack[2]; + + if (!FIRCLSReadMemory((vm_address_t)framePointer, stack, sizeof(stack))) { + // unable to read the first stack frame + FIRCLSSDKLog("Error: failed to read memory at address %p\n", (void*)framePointer); + return false; + } + + if (!FIRCLSThreadContextSetPC(registers, stack[1])) { + return false; + } + + if (!FIRCLSThreadContextSetFramePointer(registers, stack[0])) { + return false; + } + + if (!FIRCLSThreadContextSetStackPointer(registers, + FIRCLSUnwindStackPointerFromFramePointer(framePointer))) { + return false; + } + + return true; +} + +uintptr_t FIRCLSUnwindStackPointerFromFramePointer(uintptr_t framePtr) { + // the stack pointer is the frame pointer plus the two saved pointers for the frame + return framePtr + 2 * sizeof(void*); +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeRegisters(FIRCLSCompactUnwindContext* context, + FIRCLSCompactUnwindResult* result, + FIRCLSThreadContext* registers) { + if (!context || !result || !registers) { + return false; + } + + // Note that compact_uwnind_encoding.h has a few bugs in it prior to iOS 8.0. + // Only refer to the >= 8.0 header. + switch (result->encoding & UNWIND_ARM64_MODE_MASK) { + case UNWIND_ARM64_MODE_FRAMELESS: + // Interestingly, we also know the size of the stack frame, by + // using UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK. Is that useful? + return FIRCLSUnwindWithLRRegister(registers); + break; + case UNWIND_ARM64_MODE_DWARF: + return FIRCLSCompactUnwindDwarfFrame( + context, result->encoding & UNWIND_ARM64_DWARF_SECTION_OFFSET, registers); + break; + case UNWIND_ARM64_MODE_FRAME: + return FIRCLSUnwindWithFramePointer(registers, false); + default: + FIRCLSSDKLog("Invalid encoding 0x%x\n", result->encoding); + break; + } + + return false; +} +#endif + +#if CLS_DWARF_UNWINDING_SUPPORTED +uintptr_t FIRCLSDwarfUnwindGetRegisterValue(const FIRCLSThreadContext* registers, uint64_t num) { + switch (num) { + case CLS_DWARF_ARM64_X0: + return registers->__ss.__x[0]; + case CLS_DWARF_ARM64_X1: + return registers->__ss.__x[1]; + case CLS_DWARF_ARM64_X2: + return registers->__ss.__x[2]; + case CLS_DWARF_ARM64_X3: + return registers->__ss.__x[3]; + case CLS_DWARF_ARM64_X4: + return registers->__ss.__x[4]; + case CLS_DWARF_ARM64_X5: + return registers->__ss.__x[5]; + case CLS_DWARF_ARM64_X6: + return registers->__ss.__x[6]; + case CLS_DWARF_ARM64_X7: + return registers->__ss.__x[7]; + case CLS_DWARF_ARM64_X8: + return registers->__ss.__x[8]; + case CLS_DWARF_ARM64_X9: + return registers->__ss.__x[9]; + case CLS_DWARF_ARM64_X10: + return registers->__ss.__x[10]; + case CLS_DWARF_ARM64_X11: + return registers->__ss.__x[11]; + case CLS_DWARF_ARM64_X12: + return registers->__ss.__x[12]; + case CLS_DWARF_ARM64_X13: + return registers->__ss.__x[13]; + case CLS_DWARF_ARM64_X14: + return registers->__ss.__x[14]; + case CLS_DWARF_ARM64_X15: + return registers->__ss.__x[15]; + case CLS_DWARF_ARM64_X16: + return registers->__ss.__x[16]; + case CLS_DWARF_ARM64_X17: + return registers->__ss.__x[17]; + case CLS_DWARF_ARM64_X18: + return registers->__ss.__x[18]; + case CLS_DWARF_ARM64_X19: + return registers->__ss.__x[19]; + case CLS_DWARF_ARM64_X20: + return registers->__ss.__x[20]; + case CLS_DWARF_ARM64_X21: + return registers->__ss.__x[21]; + case CLS_DWARF_ARM64_X22: + return registers->__ss.__x[22]; + case CLS_DWARF_ARM64_X23: + return registers->__ss.__x[23]; + case CLS_DWARF_ARM64_X24: + return registers->__ss.__x[24]; + case CLS_DWARF_ARM64_X25: + return registers->__ss.__x[25]; + case CLS_DWARF_ARM64_X26: + return registers->__ss.__x[26]; + case CLS_DWARF_ARM64_X27: + return registers->__ss.__x[27]; + case CLS_DWARF_ARM64_X28: + return registers->__ss.__x[28]; + case CLS_DWARF_ARM64_FP: + return FIRCLSThreadContextGetFramePointer(registers); + case CLS_DWARF_ARM64_LR: + return FIRCLSThreadContextGetLinkRegister(registers); + case CLS_DWARF_ARM64_SP: + return FIRCLSThreadContextGetStackPointer(registers); + default: + break; + } + + FIRCLSSDKLog("Error: Unrecognized get register number %llu\n", num); + + return 0; +} + +bool FIRCLSDwarfUnwindSetRegisterValue(FIRCLSThreadContext* registers, + uint64_t num, + uintptr_t value) { + switch (num) { + case CLS_DWARF_ARM64_X0: + registers->__ss.__x[0] = value; + return true; + case CLS_DWARF_ARM64_X1: + registers->__ss.__x[1] = value; + return true; + case CLS_DWARF_ARM64_X2: + registers->__ss.__x[2] = value; + return true; + case CLS_DWARF_ARM64_X3: + registers->__ss.__x[3] = value; + return true; + case CLS_DWARF_ARM64_X4: + registers->__ss.__x[4] = value; + return true; + case CLS_DWARF_ARM64_X5: + registers->__ss.__x[5] = value; + return true; + case CLS_DWARF_ARM64_X6: + registers->__ss.__x[6] = value; + return true; + case CLS_DWARF_ARM64_X7: + registers->__ss.__x[7] = value; + return true; + case CLS_DWARF_ARM64_X8: + registers->__ss.__x[8] = value; + return true; + case CLS_DWARF_ARM64_X9: + registers->__ss.__x[9] = value; + return true; + case CLS_DWARF_ARM64_X10: + registers->__ss.__x[10] = value; + return true; + case CLS_DWARF_ARM64_X11: + registers->__ss.__x[11] = value; + return true; + case CLS_DWARF_ARM64_X12: + registers->__ss.__x[12] = value; + return true; + case CLS_DWARF_ARM64_X13: + registers->__ss.__x[13] = value; + return true; + case CLS_DWARF_ARM64_X14: + registers->__ss.__x[14] = value; + return true; + case CLS_DWARF_ARM64_X15: + registers->__ss.__x[15] = value; + return true; + case CLS_DWARF_ARM64_X16: + registers->__ss.__x[16] = value; + return true; + case CLS_DWARF_ARM64_X17: + registers->__ss.__x[17] = value; + return true; + case CLS_DWARF_ARM64_X18: + registers->__ss.__x[18] = value; + return true; + case CLS_DWARF_ARM64_X19: + registers->__ss.__x[19] = value; + return true; + case CLS_DWARF_ARM64_X20: + registers->__ss.__x[20] = value; + return true; + case CLS_DWARF_ARM64_X21: + registers->__ss.__x[21] = value; + return true; + case CLS_DWARF_ARM64_X22: + registers->__ss.__x[22] = value; + return true; + case CLS_DWARF_ARM64_X23: + registers->__ss.__x[23] = value; + return true; + case CLS_DWARF_ARM64_X24: + registers->__ss.__x[24] = value; + return true; + case CLS_DWARF_ARM64_X25: + registers->__ss.__x[25] = value; + return true; + case CLS_DWARF_ARM64_X26: + registers->__ss.__x[26] = value; + return true; + case CLS_DWARF_ARM64_X27: + registers->__ss.__x[27] = value; + return true; + case CLS_DWARF_ARM64_X28: + registers->__ss.__x[28] = value; + return true; + case CLS_DWARF_ARM64_FP: + FIRCLSThreadContextSetFramePointer(registers, value); + return true; + case CLS_DWARF_ARM64_SP: + FIRCLSThreadContextSetStackPointer(registers, value); + return true; + case CLS_DWARF_ARM64_LR: + // Here's what's going on. For x86, the "return register" is virtual. The architecture + // doesn't actually have one, but DWARF does have the concept. So, when the system + // tries to set the return register, we set the PC. You can see this behavior + // in the FIRCLSDwarfUnwindSetRegisterValue implemenation for that architecture. In the + // case of ARM64, the register is real. So, we have to be extra careful to make sure + // we update the PC here. Otherwise, when a DWARF unwind completes, it won't have + // changed the PC to the right value. + FIRCLSThreadContextSetLinkRegister(registers, value); + FIRCLSThreadContextSetPC(registers, value); + return true; + default: + break; + } + + FIRCLSSDKLog("Unrecognized set register number %llu\n", num); + + return false; +} +#endif + +#else +INJECT_STRIP_SYMBOL(unwind_arm) +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.c new file mode 100644 index 00000000..c4780a12 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.c @@ -0,0 +1,537 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h" +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind_Private.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h" +#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind.h" +#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h" +#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h" + +#if CLS_CPU_X86 + +static bool FIRCLSCompactUnwindBPFrame(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers); +static bool FIRCLSCompactUnwindFrameless(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uintptr_t functionStart, + bool indirect); + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeRegisters(FIRCLSCompactUnwindContext* context, + FIRCLSCompactUnwindResult* result, + FIRCLSThreadContext* registers) { + if (!FIRCLSIsValidPointer(context) || !FIRCLSIsValidPointer(result) || + !FIRCLSIsValidPointer(registers)) { + FIRCLSSDKLogError("invalid inputs\n"); + return false; + } + + FIRCLSSDKLogDebug("Computing registers for encoding %x\n", result->encoding); + + switch (result->encoding & CLS_X86_MODE_MASK) { + case CLS_X86_MODE_BP_FRAME: + return FIRCLSCompactUnwindBPFrame(result->encoding, registers); + case CLS_X86_MODE_STACK_IMMD: + return FIRCLSCompactUnwindFrameless(result->encoding, registers, result->functionStart, + false); + case CLS_X86_MODE_STACK_IND: + return FIRCLSCompactUnwindFrameless(result->encoding, registers, result->functionStart, true); + case CLS_X86_MODE_DWARF: + return FIRCLSCompactUnwindDwarfFrame(context, result->encoding & CLS_X86_DWARF_SECTION_OFFSET, + registers); + default: + FIRCLSSDKLogError("Invalid encoding %x\n", result->encoding); + break; + } + + return false; +} +#endif + +static bool FIRCLSCompactUnwindBPFrame(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers) { + // this is the plain-vanilla frame pointer process + + // uint32_t offset = GET_BITS_WITH_MASK(encoding, UNWIND_X86_EBP_FRAME_OFFSET); + // uint32_t locations = GET_BITS_WITH_MASK(encoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); + + // TODO: pretty sure we do need to restore registers here, so that if a subsequent frame needs + // these results, they will be correct + + // Checkout CompactUnwinder.hpp in libunwind for how to do this. Since we don't make use of any of + // those registers for a stacktrace only, there's nothing we need do with them. + + // read the values from the stack + const uintptr_t framePointer = FIRCLSThreadContextGetFramePointer(registers); + uintptr_t stack[2]; + + if (!FIRCLSReadMemory((vm_address_t)framePointer, stack, sizeof(stack))) { + // unable to read the first stack frame + FIRCLSSDKLog("Error: failed to read memory at address %p\n", (void*)framePointer); + return false; + } + + if (!FIRCLSThreadContextSetPC(registers, stack[1])) { + return false; + } + + if (!FIRCLSThreadContextSetFramePointer(registers, stack[0])) { + return false; + } + + if (!FIRCLSThreadContextSetStackPointer(registers, + FIRCLSUnwindStackPointerFromFramePointer(framePointer))) { + return false; + } + + return true; +} + +bool FIRCLSUnwindWithStackScanning(FIRCLSThreadContext* registers) { + vm_address_t start = (vm_address_t)FIRCLSThreadContextGetStackPointer(registers); + vm_address_t end = (vm_address_t)FIRCLSThreadContextGetFramePointer(registers); + + uintptr_t newPC = 0; + + if (!FIRCLSUnwindFirstExecutableAddress(start, end, (vm_address_t*)&newPC)) { + return false; + } + + return FIRCLSThreadContextSetPC(registers, newPC); +} + +bool FIRCLSUnwindWithFramePointer(FIRCLSThreadContext* registers, bool allowScanning) { + // Here's an interesting case. We've just processed the first frame, and it did + // not have any unwind info. If that first function did not allocate + // a stack frame, we'll "skip" the caller. This might sound unlikely, but it actually + // happens a lot in practice. + + // Sooo, one thing we can do is try to stack the stack for things that look like return + // addresses. Normally, this technique will hit many false positives. But, if we do it + // only for the second frame, and only when we don't have other unwind info available. + + if (allowScanning) { + FIRCLSSDKLogInfo("Attempting stack scan\n"); + if (FIRCLSUnwindWithStackScanning(registers)) { + FIRCLSSDKLogInfo("Stack scan successful\n"); + return true; + } + } + + // If we ever do anything else with the encoding, we need to be sure + // to set it up right. + return FIRCLSCompactUnwindBPFrame(CLS_X86_MODE_BP_FRAME, registers); +} + +uintptr_t FIRCLSUnwindStackPointerFromFramePointer(uintptr_t framePtr) { + // the stack pointer is the frame pointer plus the two saved pointers for the frame + return framePtr + 2 * sizeof(void*); +} + +#if CLS_COMPACT_UNWINDING_SUPPORTED || CLS_DWARF_UNWINDING_SUPPORTED +uintptr_t FIRCLSDwarfUnwindGetRegisterValue(const FIRCLSThreadContext* registers, uint64_t num) { + switch (num) { +#if CLS_CPU_X86_64 + case CLS_DWARF_X86_64_RAX: + return registers->__ss.__rax; + case CLS_DWARF_X86_64_RDX: + return registers->__ss.__rdx; + case CLS_DWARF_X86_64_RCX: + return registers->__ss.__rcx; + case CLS_DWARF_X86_64_RBX: + return registers->__ss.__rbx; + case CLS_DWARF_X86_64_RSI: + return registers->__ss.__rsi; + case CLS_DWARF_X86_64_RDI: + return registers->__ss.__rdi; + case CLS_DWARF_X86_64_RBP: + return registers->__ss.__rbp; + case CLS_DWARF_X86_64_RSP: + return registers->__ss.__rsp; + case CLS_DWARF_X86_64_R8: + return registers->__ss.__r8; + case CLS_DWARF_X86_64_R9: + return registers->__ss.__r9; + case CLS_DWARF_X86_64_R10: + return registers->__ss.__r10; + case CLS_DWARF_X86_64_R11: + return registers->__ss.__r11; + case CLS_DWARF_X86_64_R12: + return registers->__ss.__r12; + case CLS_DWARF_X86_64_R13: + return registers->__ss.__r13; + case CLS_DWARF_X86_64_R14: + return registers->__ss.__r14; + case CLS_DWARF_X86_64_R15: + return registers->__ss.__r15; + case CLS_DWARF_X86_64_RET_ADDR: + return registers->__ss.__rip; +#elif CLS_CPU_I386 + case CLS_DWARF_X86_EAX: + return registers->__ss.__eax; + case CLS_DWARF_X86_ECX: + return registers->__ss.__ecx; + case CLS_DWARF_X86_EDX: + return registers->__ss.__edx; + case CLS_DWARF_X86_EBX: + return registers->__ss.__ebx; + case CLS_DWARF_X86_EBP: + return registers->__ss.__ebp; + case CLS_DWARF_X86_ESP: + return registers->__ss.__esp; + case CLS_DWARF_X86_ESI: + return registers->__ss.__esi; + case CLS_DWARF_X86_EDI: + return registers->__ss.__edi; + case CLS_DWARF_X86_RET_ADDR: + return registers->__ss.__eip; +#endif + default: + break; + } + + FIRCLSSDKLog("Error: Unrecognized get register number %llu\n", num); + + return 0; +} + +bool FIRCLSDwarfUnwindSetRegisterValue(FIRCLSThreadContext* registers, + uint64_t num, + uintptr_t value) { + switch (num) { +#if CLS_CPU_X86_64 + case CLS_DWARF_X86_64_RAX: + registers->__ss.__rax = value; + return true; + case CLS_DWARF_X86_64_RDX: + registers->__ss.__rdx = value; + return true; + case CLS_DWARF_X86_64_RCX: + registers->__ss.__rcx = value; + return true; + case CLS_DWARF_X86_64_RBX: + registers->__ss.__rbx = value; + return true; + case CLS_DWARF_X86_64_RSI: + registers->__ss.__rsi = value; + return true; + case CLS_DWARF_X86_64_RDI: + registers->__ss.__rdi = value; + return true; + case CLS_DWARF_X86_64_RBP: + registers->__ss.__rbp = value; + return true; + case CLS_DWARF_X86_64_RSP: + registers->__ss.__rsp = value; + return true; + case CLS_DWARF_X86_64_R8: + registers->__ss.__r8 = value; + return true; + case CLS_DWARF_X86_64_R9: + registers->__ss.__r9 = value; + return true; + case CLS_DWARF_X86_64_R10: + registers->__ss.__r10 = value; + return true; + case CLS_DWARF_X86_64_R11: + registers->__ss.__r11 = value; + return true; + case CLS_DWARF_X86_64_R12: + registers->__ss.__r12 = value; + return true; + case CLS_DWARF_X86_64_R13: + registers->__ss.__r13 = value; + return true; + case CLS_DWARF_X86_64_R14: + registers->__ss.__r14 = value; + return true; + case CLS_DWARF_X86_64_R15: + registers->__ss.__r15 = value; + return true; + case CLS_DWARF_X86_64_RET_ADDR: + registers->__ss.__rip = value; + return true; +#elif CLS_CPU_I386 + case CLS_DWARF_X86_EAX: + registers->__ss.__eax = value; + return true; + case CLS_DWARF_X86_ECX: + registers->__ss.__ecx = value; + return true; + case CLS_DWARF_X86_EDX: + registers->__ss.__edx = value; + return true; + case CLS_DWARF_X86_EBX: + registers->__ss.__ebx = value; + return true; + case CLS_DWARF_X86_EBP: + registers->__ss.__ebp = value; + return true; + case CLS_DWARF_X86_ESP: + registers->__ss.__esp = value; + return true; + case CLS_DWARF_X86_ESI: + registers->__ss.__esi = value; + return true; + case CLS_DWARF_X86_EDI: + registers->__ss.__edi = value; + return true; + case CLS_DWARF_X86_RET_ADDR: + registers->__ss.__eip = value; + return true; +#endif + default: + break; + } + + FIRCLSSDKLog("Unrecognized set register number %llu\n", num); + + return false; +} +#endif + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeStackSize(const compact_unwind_encoding_t encoding, + const uintptr_t functionStart, + const bool indirect, + uint32_t* const stackSize) { + if (!FIRCLSIsValidPointer(stackSize)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + const uint32_t stackSizeEncoded = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_SIZE); + + if (!indirect) { + *stackSize = stackSizeEncoded * sizeof(void*); + return true; + } + + const vm_address_t sublAddress = functionStart + stackSizeEncoded; + uint32_t sublValue = 0; + + if (!FIRCLSReadMemory(sublAddress, &sublValue, sizeof(uint32_t))) { + FIRCLSSDKLog("Error: unable to read subl value\n"); + return false; + } + + const uint32_t stackAdjust = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_ADJUST); + + *stackSize = sublValue + stackAdjust * sizeof(void*); + + return true; +} + +bool FIRCLSCompactUnwindDecompressPermutation(const compact_unwind_encoding_t encoding, + uintptr_t permutatedRegisters[const static 6]) { + const uint32_t regCount = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_COUNT); + uint32_t permutation = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_PERMUTATION); + + switch (regCount) { + case 6: + permutatedRegisters[0] = permutation / 120; + permutation -= (permutatedRegisters[0] * 120); + permutatedRegisters[1] = permutation / 24; + permutation -= (permutatedRegisters[1] * 24); + permutatedRegisters[2] = permutation / 6; + permutation -= (permutatedRegisters[2] * 6); + permutatedRegisters[3] = permutation / 2; + permutation -= (permutatedRegisters[3] * 2); + permutatedRegisters[4] = permutation; + permutatedRegisters[5] = 0; + break; + case 5: + permutatedRegisters[0] = permutation / 120; + permutation -= (permutatedRegisters[0] * 120); + permutatedRegisters[1] = permutation / 24; + permutation -= (permutatedRegisters[1] * 24); + permutatedRegisters[2] = permutation / 6; + permutation -= (permutatedRegisters[2] * 6); + permutatedRegisters[3] = permutation / 2; + permutation -= (permutatedRegisters[3] * 2); + permutatedRegisters[4] = permutation; + break; + case 4: + permutatedRegisters[0] = permutation / 60; + permutation -= (permutatedRegisters[0] * 60); + permutatedRegisters[1] = permutation / 12; + permutation -= (permutatedRegisters[1] * 12); + permutatedRegisters[2] = permutation / 3; + permutation -= (permutatedRegisters[2] * 3); + permutatedRegisters[3] = permutation; + break; + case 3: + permutatedRegisters[0] = permutation / 20; + permutation -= (permutatedRegisters[0] * 20); + permutatedRegisters[1] = permutation / 4; + permutation -= (permutatedRegisters[1] * 4); + permutatedRegisters[2] = permutation; + break; + case 2: + permutatedRegisters[0] = permutation / 5; + permutation -= (permutatedRegisters[0] * 5); + permutatedRegisters[1] = permutation; + break; + case 1: + permutatedRegisters[0] = permutation; + break; + case 0: + break; + default: + FIRCLSSDKLog("Error: unhandled number of register permutations for encoding %x\n", encoding); + return false; + } + + return true; +} + +bool FIRCLSCompactUnwindRemapRegisters(const compact_unwind_encoding_t encoding, + uintptr_t permutatedRegisters[const static 6], + uintptr_t savedRegisters[const static 6]) { + const uint32_t regCount = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_COUNT); + + if (regCount > 6) { + FIRCLSSDKLog("Error: invalid register number count %d\n", regCount); + return false; + } + + // Re-number the registers + + // You are probably wondering, what the hell is this algorithm even doing? It is + // taken from libunwind's implemenation that does the same thing. + bool used[7] = {false, false, false, false, false, false, false}; + for (uint32_t i = 0; i < regCount; ++i) { + int renum = 0; + for (int u = 1; u < 7; ++u) { + if (!used[u]) { + if (renum == permutatedRegisters[i]) { + savedRegisters[i] = u; + used[u] = true; + break; + } + ++renum; + } + } + } + + return true; +} + +bool FIRCLSCompactUnwindRestoreRegisters(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uint32_t stackSize, + const uintptr_t savedRegisters[const static 6], + uintptr_t* address) { + if (!FIRCLSIsValidPointer(registers) || !FIRCLSIsValidPointer(address)) { + FIRCLSSDKLog("Error: invalid inputs\n"); + return false; + } + + const uint32_t regCount = GET_BITS_WITH_MASK(encoding, CLS_X86_FRAMELESS_STACK_REG_COUNT); + + // compute initial address of saved registers + *address = FIRCLSThreadContextGetStackPointer(registers) + stackSize - sizeof(void*) - + sizeof(void*) * regCount; + uintptr_t value = 0; + + for (uint32_t i = 0; i < regCount; ++i) { + value = 0; + + switch (savedRegisters[i]) { + case CLS_X86_REG_RBP: + if (!FIRCLSReadMemory((vm_address_t)*address, (void*)&value, sizeof(uintptr_t))) { + FIRCLSSDKLog("Error: unable to read memory to set register\n"); + return false; + } + + if (!FIRCLSThreadContextSetFramePointer(registers, value)) { + FIRCLSSDKLog("Error: unable to set FP\n"); + return false; + } + break; + default: + // here, we are restoring a register we don't need for unwinding + FIRCLSSDKLog("Error: skipping a restore of register %d at %p\n", (int)savedRegisters[i], + (void*)*address); + break; + } + + *address += sizeof(void*); + } + + return true; +} + +static bool FIRCLSCompactUnwindFrameless(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uintptr_t functionStart, + bool indirect) { + FIRCLSSDKLog("Frameless unwind encountered with encoding %x\n", encoding); + + uint32_t stackSize = 0; + if (!FIRCLSCompactUnwindComputeStackSize(encoding, functionStart, indirect, &stackSize)) { + FIRCLSSDKLog("Error: unable to compute stack size for encoding %x\n", encoding); + return false; + } + + uintptr_t permutatedRegisters[6]; + + memset(permutatedRegisters, 0, sizeof(permutatedRegisters)); + if (!FIRCLSCompactUnwindDecompressPermutation(encoding, permutatedRegisters)) { + FIRCLSSDKLog("Error: unable to decompress registers %x\n", encoding); + return false; + } + + uintptr_t savedRegisters[6]; + + memset(savedRegisters, 0, sizeof(savedRegisters)); + if (!FIRCLSCompactUnwindRemapRegisters(encoding, permutatedRegisters, savedRegisters)) { + FIRCLSSDKLog("Error: unable to remap registers %x\n", encoding); + return false; + } + + uintptr_t address = 0; + + if (!FIRCLSCompactUnwindRestoreRegisters(encoding, registers, stackSize, savedRegisters, + &address)) { + FIRCLSSDKLog("Error: unable to restore registers\n"); + return false; + } + + FIRCLSSDKLog("SP is %p and we are reading %p\n", + (void*)FIRCLSThreadContextGetStackPointer(registers), (void*)address); + // read the value from the stack, now that we know the address to read + uintptr_t value = 0; + if (!FIRCLSReadMemory((vm_address_t)address, (void*)&value, sizeof(uintptr_t))) { + FIRCLSSDKLog("Error: unable to read memory to set register\n"); + return false; + } + + FIRCLSSDKLog("Read PC to be %p\n", (void*)value); + if (!FIRCLSIsValidPointer(value)) { + FIRCLSSDKLog("Error: computed PC is invalid\n"); + return false; + } + + return FIRCLSThreadContextSetPC(registers, value) && + FIRCLSThreadContextSetStackPointer(registers, address + sizeof(void*)); +} +#endif + +#else +INJECT_STRIP_SYMBOL(unwind_x86) +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h new file mode 100644 index 00000000..849da288 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_x86.h @@ -0,0 +1,76 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include "Crashlytics/Crashlytics/Helpers/FIRCLSFeatures.h" +#include "Crashlytics/Crashlytics/Unwind/Compact/FIRCLSCompactUnwind.h" + +// Add some abstraction to compact unwinding, because compact +// unwinding is nearly identical between 32 and 64 bit +#if CLS_CPU_X86_64 + +#define CLS_X86_MODE_MASK UNWIND_X86_64_MODE_MASK +#define CLS_X86_MODE_BP_FRAME UNWIND_X86_64_MODE_RBP_FRAME +#define CLS_X86_MODE_STACK_IMMD UNWIND_X86_64_MODE_STACK_IMMD +#define CLS_X86_MODE_STACK_IND UNWIND_X86_64_MODE_STACK_IND +#define CLS_X86_MODE_DWARF UNWIND_X86_64_MODE_DWARF + +#define CLS_X86_BP_FRAME_REGISTERS UNWIND_X86_64_RBP_FRAME_REGISTERS +#define CLS_X86_BP_FRAME_OFFSET UNWIND_X86_64_RBP_FRAME_OFFSET + +#define CLS_X86_FRAMELESS_STACK_SIZE UNWIND_X86_64_FRAMELESS_STACK_SIZE +#define CLS_X86_FRAMELESS_STACK_ADJUST UNWIND_X86_64_FRAMELESS_STACK_ADJUST +#define CLS_X86_FRAMELESS_STACK_REG_COUNT UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT +#define CLS_X86_FRAMELESS_STACK_REG_PERMUTATION UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION + +#define CLS_X86_DWARF_SECTION_OFFSET UNWIND_X86_64_DWARF_SECTION_OFFSET + +#define CLS_X86_REG_RBP UNWIND_X86_64_REG_RBP + +#else + +#define CLS_X86_MODE_MASK UNWIND_X86_MODE_MASK +#define CLS_X86_MODE_BP_FRAME UNWIND_X86_MODE_EBP_FRAME +#define CLS_X86_MODE_STACK_IMMD UNWIND_X86_MODE_STACK_IMMD +#define CLS_X86_MODE_STACK_IND UNWIND_X86_MODE_STACK_IND +#define CLS_X86_MODE_DWARF UNWIND_X86_MODE_DWARF + +#define CLS_X86_BP_FRAME_REGISTERS UNWIND_X86_RBP_FRAME_REGISTERS +#define CLS_X86_BP_FRAME_OFFSET UNWIND_X86_RBP_FRAME_OFFSET + +#define CLS_X86_FRAMELESS_STACK_SIZE UNWIND_X86_FRAMELESS_STACK_SIZE +#define CLS_X86_FRAMELESS_STACK_ADJUST UNWIND_X86_FRAMELESS_STACK_ADJUST +#define CLS_X86_FRAMELESS_STACK_REG_COUNT UNWIND_X86_FRAMELESS_STACK_REG_COUNT +#define CLS_X86_FRAMELESS_STACK_REG_PERMUTATION UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION + +#define CLS_X86_DWARF_SECTION_OFFSET UNWIND_X86_DWARF_SECTION_OFFSET + +#define CLS_X86_REG_RBP UNWIND_X86_REG_EBP + +#endif + +#if CLS_COMPACT_UNWINDING_SUPPORTED +bool FIRCLSCompactUnwindComputeStackSize(const compact_unwind_encoding_t encoding, + const uintptr_t functionStart, + const bool indirect, + uint32_t* const stackSize); +bool FIRCLSCompactUnwindDecompressPermutation(const compact_unwind_encoding_t encoding, + uintptr_t permutatedRegisters[const static 6]); +bool FIRCLSCompactUnwindRestoreRegisters(compact_unwind_encoding_t encoding, + FIRCLSThreadContext* registers, + uint32_t stackSize, + const uintptr_t savedRegisters[const static 6], + uintptr_t* address); +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/LICENSE b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/LICENSE new file mode 100644 index 00000000..925bc57f --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/LICENSE @@ -0,0 +1,230 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + +================================================================================ + +The following copyright from Hewlett-Packard Development Company, L.P. +applies to the dwarf.h file in third_party/libunwind + + libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang <davidm@hpl.hp.com> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.c b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.c new file mode 100644 index 00000000..6b927408 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.c @@ -0,0 +1,75 @@ +/* + * Copyright 2019 Google + * + * 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. + */ + +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.3.9.5 */ + +#include "Crashlytics/Protogen/nanopb/crashlytics.nanopb.h" + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + + +const pb_field_t google_crashlytics_Report_fields[8] = { + PB_FIELD( 1, BYTES , SINGULAR, POINTER , FIRST, google_crashlytics_Report, sdk_version, sdk_version, 0), + PB_FIELD( 3, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, gmp_app_id, sdk_version, 0), + PB_FIELD( 4, UENUM , SINGULAR, STATIC , OTHER, google_crashlytics_Report, platform, gmp_app_id, 0), + PB_FIELD( 5, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, installation_uuid, platform, 0), + PB_FIELD( 6, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, build_version, installation_uuid, 0), + PB_FIELD( 7, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_Report, display_version, build_version, 0), + PB_FIELD( 10, MESSAGE , SINGULAR, STATIC , OTHER, google_crashlytics_Report, apple_payload, display_version, &google_crashlytics_FilesPayload_fields), + PB_LAST_FIELD +}; + +const pb_field_t google_crashlytics_FilesPayload_fields[2] = { + PB_FIELD( 1, MESSAGE , REPEATED, POINTER , FIRST, google_crashlytics_FilesPayload, files, files, &google_crashlytics_FilesPayload_File_fields), + PB_LAST_FIELD +}; + +const pb_field_t google_crashlytics_FilesPayload_File_fields[3] = { + PB_FIELD( 1, BYTES , SINGULAR, POINTER , FIRST, google_crashlytics_FilesPayload_File, filename, filename, 0), + PB_FIELD( 2, BYTES , SINGULAR, POINTER , OTHER, google_crashlytics_FilesPayload_File, contents, filename, 0), + PB_LAST_FIELD +}; + + + +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(google_crashlytics_Report, apple_payload) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_google_crashlytics_Report_google_crashlytics_FilesPayload_google_crashlytics_FilesPayload_File) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(google_crashlytics_Report, apple_payload) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_google_crashlytics_Report_google_crashlytics_FilesPayload_google_crashlytics_FilesPayload_File) +#endif + + +/* @@protoc_insertion_point(eof) */ diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h new file mode 100644 index 00000000..51e05ed2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Protogen/nanopb/crashlytics.nanopb.h @@ -0,0 +1,111 @@ +/* + * Copyright 2019 Google + * + * 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. + */ + +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.3.9.5 */ + +#ifndef PB_GOOGLE_CRASHLYTICS_CRASHLYTICS_NANOPB_H_INCLUDED +#define PB_GOOGLE_CRASHLYTICS_CRASHLYTICS_NANOPB_H_INCLUDED +#if SWIFT_PACKAGE +#include "nanopb.h" +#else +#include <nanopb/pb.h> +#endif + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 +#error Regenerate this file with the current version of nanopb generator. +#endif + + +/* Enum definitions */ +typedef enum _google_crashlytics_Platforms { + google_crashlytics_Platforms_UNKNOWN_PLATFORM = 0, + google_crashlytics_Platforms_IOS = 1, + google_crashlytics_Platforms_TVOS = 2, + google_crashlytics_Platforms_MAC_OS_X = 5 +} google_crashlytics_Platforms; +#define _google_crashlytics_Platforms_MIN google_crashlytics_Platforms_UNKNOWN_PLATFORM +#define _google_crashlytics_Platforms_MAX google_crashlytics_Platforms_MAC_OS_X +#define _google_crashlytics_Platforms_ARRAYSIZE ((google_crashlytics_Platforms)(google_crashlytics_Platforms_MAC_OS_X+1)) + +/* Struct definitions */ +typedef struct _google_crashlytics_FilesPayload { + pb_size_t files_count; + struct _google_crashlytics_FilesPayload_File *files; +/* @@protoc_insertion_point(struct:google_crashlytics_FilesPayload) */ +} google_crashlytics_FilesPayload; + +typedef struct _google_crashlytics_FilesPayload_File { + pb_bytes_array_t *filename; + pb_bytes_array_t *contents; +/* @@protoc_insertion_point(struct:google_crashlytics_FilesPayload_File) */ +} google_crashlytics_FilesPayload_File; + +typedef struct _google_crashlytics_Report { + pb_bytes_array_t *sdk_version; + pb_bytes_array_t *gmp_app_id; + google_crashlytics_Platforms platform; + pb_bytes_array_t *installation_uuid; + pb_bytes_array_t *build_version; + pb_bytes_array_t *display_version; + google_crashlytics_FilesPayload apple_payload; +/* @@protoc_insertion_point(struct:google_crashlytics_Report) */ +} google_crashlytics_Report; + +/* Default values for struct fields */ + +/* Initializer values for message structs */ +#define google_crashlytics_Report_init_default {NULL, NULL, _google_crashlytics_Platforms_MIN, NULL, NULL, NULL, google_crashlytics_FilesPayload_init_default} +#define google_crashlytics_FilesPayload_init_default {0, NULL} +#define google_crashlytics_FilesPayload_File_init_default {NULL, NULL} +#define google_crashlytics_Report_init_zero {NULL, NULL, _google_crashlytics_Platforms_MIN, NULL, NULL, NULL, google_crashlytics_FilesPayload_init_zero} +#define google_crashlytics_FilesPayload_init_zero {0, NULL} +#define google_crashlytics_FilesPayload_File_init_zero {NULL, NULL} + +/* Field tags (for use in manual encoding/decoding) */ +#define google_crashlytics_FilesPayload_files_tag 1 +#define google_crashlytics_FilesPayload_File_filename_tag 1 +#define google_crashlytics_FilesPayload_File_contents_tag 2 +#define google_crashlytics_Report_sdk_version_tag 1 +#define google_crashlytics_Report_gmp_app_id_tag 3 +#define google_crashlytics_Report_platform_tag 4 +#define google_crashlytics_Report_installation_uuid_tag 5 +#define google_crashlytics_Report_build_version_tag 6 +#define google_crashlytics_Report_display_version_tag 7 +#define google_crashlytics_Report_apple_payload_tag 10 + +/* Struct field encoding specification for nanopb */ +extern const pb_field_t google_crashlytics_Report_fields[8]; +extern const pb_field_t google_crashlytics_FilesPayload_fields[2]; +extern const pb_field_t google_crashlytics_FilesPayload_File_fields[3]; + +/* Maximum encoded size of messages (where known) */ +/* google_crashlytics_Report_size depends on runtime parameters */ +/* google_crashlytics_FilesPayload_size depends on runtime parameters */ +/* google_crashlytics_FilesPayload_File_size depends on runtime parameters */ + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define CRASHLYTICS_MESSAGES \ + + +#endif + +/* @@protoc_insertion_point(eof) */ + +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/README.md b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/README.md new file mode 100644 index 00000000..55d36e65 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/README.md @@ -0,0 +1,39 @@ +# Firebase Crashlytics SDK + +## Development + +Follow the subsequent instructions to develop, debug, unit test, and +integration test FirebaseCrashlytics: + +### Prereqs + +- At least CocoaPods 1.6.0 +- Install [cocoapods-generate](https://github.com/square/cocoapods-generate) +- For nanopb and GDT: + - `brew install protobuf nanopb-generator` + - `easy_install protobuf python` + +### To Develop + +- Run `Crashlytics/generate_project.sh` +- `open gen/FirebaseCrashlytics/FirebaseCrashlytics.xcworkspace` + +You're now in an Xcode workspace generate for building, debugging and +testing the FirebaseCrashlytics CocoaPod. + +### Running Unit Tests + +Open the generated workspace, choose the FirebaseCrashlytics-Unit-unit scheme and press Command-u. + +### Changing crash report uploads (using GDT) + +#### Update report proto + +If the crash report proto needs to be updated, follow these instructions: + +- Update `ProtoSupport/Protos/crashlytics.proto` with the new changes +- Depending on the type of fields added/removed, also update `ProtoSupport/Protos/crashlytics.options`. + `CALLBACK` type fields in crashlytics.nanopb.c needs to be changed to `POINTER` + (through the options file). Known field types that require an entry in crashlytics.options are + `strings`, `repeated` and `bytes`. +- Run `generate_project.sh` to update the nanopb .c/.h files.
\ No newline at end of file diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h new file mode 100644 index 00000000..ca2abb81 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.h @@ -0,0 +1,41 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +/** + * Returns a SHA1 Hash of the input NSData + */ +NSString *FIRCLSHashNSData(NSData *data); +/** + * Returns a SHA256 Hash of the input NSData + */ +NSString *FIRCLS256HashNSData(NSData *data); +/** + * Returns a SHA1 Hash of the input bytes + */ +NSString *FIRCLSHashBytes(const void *bytes, size_t length); +/** + * Populates a Hex value conversion of value into outputBuffer. + * If value is nil, then outputBuffer is not modified. + */ +void FIRCLSSafeHexToString(const uint8_t *value, size_t length, char *outputBuffer); + +/** + * Iterates through the raw bytes of NSData in a way that is similar to + * -[NSData enumerateByteRangesUsingBlock:], but is safe to call from older + * OSes that do not support it. + */ +void FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + NSData *data, void (^block)(const void *bytes, NSRange byteRange, BOOL *stop)); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.m new file mode 100644 index 00000000..8298bf12 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSByteUtility.m @@ -0,0 +1,120 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSByteUtility.h" + +#import <CommonCrypto/CommonDigest.h> +#import <CommonCrypto/CommonHMAC.h> + +#pragma mark Private functions + +static const char FIRCLSHexMap[] = "0123456789abcdef"; + +void FIRCLSHexFromByte(uint8_t c, char output[]) { + if (!output) { + return; + } + + output[0] = FIRCLSHexMap[c >> 4]; + output[1] = FIRCLSHexMap[c & 0x0f]; +} + +void FIRCLSSafeHexToString(const uint8_t *value, size_t length, char *outputBuffer) { + if (!outputBuffer) { + return; + } + + memset(outputBuffer, 0, (length * 2) + 1); + + if (!value) { + return; + } + + for (size_t i = 0; i < length; ++i) { + uint8_t c = value[i]; + + FIRCLSHexFromByte(c, &outputBuffer[i * 2]); + } +} + +NSString *FIRCLSNSDataPrettyDescription(NSData *data) { + NSString *string; + char *buffer; + size_t size; + NSUInteger length; + + // we need 2 hex char for every byte of data, plus one more spot for a + // null terminator + length = data.length; + size = (length * 2) + 1; + buffer = malloc(sizeof(char) * size); + + if (!buffer) { + return nil; + } + + FIRCLSSafeHexToString(data.bytes, length, buffer); + + string = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return string; +} + +#pragma mark Public functions + +NSString *FIRCLSHashBytes(const void *bytes, size_t length) { + uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; + CC_SHA1(bytes, (CC_LONG)length, digest); + + NSData *result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + + return FIRCLSNSDataPrettyDescription(result); +} + +NSString *FIRCLSHashNSData(NSData *data) { + return FIRCLSHashBytes(data.bytes, data.length); +} + +NSString *FIRCLS256HashBytes(const void *bytes, size_t length) { + uint8_t digest[CC_SHA256_DIGEST_LENGTH] = {0}; + CC_SHA256(bytes, (CC_LONG)length, digest); + + NSData *result = [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH]; + + return FIRCLSNSDataPrettyDescription(result); +} + +NSString *FIRCLS256HashNSData(NSData *data) { + return FIRCLS256HashBytes(data.bytes, data.length); +} + +void FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + NSData *data, void (^block)(const void *bytes, NSRange byteRange, BOOL *stop)) { + if ([data respondsToSelector:@selector(enumerateByteRangesUsingBlock:)]) { + [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { + block(bytes, byteRange, stop); + }]; + + return; + } + + // Fall back to the less-efficient mechanism for older OSes. Safe + // to ignore the return value of stop, since we'll only ever + // call this once anyways + BOOL stop = NO; + + block(data.bytes, NSMakeRange(0, data.length), &stop); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h new file mode 100644 index 00000000..c17ee02c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.h @@ -0,0 +1,45 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +FOUNDATION_EXPORT NSString *const FIRCLSDeveloperToken; + +FOUNDATION_EXPORT NSString *const FIRCLSVersion; + +// User Messages +FOUNDATION_EXPORT NSString *const FIRCLSMissingConsumerKeyMsg; +FOUNDATION_EXPORT NSString *const FIRCLSMissingConsumerSecretMsg; + +// Exceptions +FOUNDATION_EXPORT NSString *const FIRCLSException; + +// Endpoints +FOUNDATION_EXPORT NSString *const FIRCLSSettingsEndpoint; +FOUNDATION_EXPORT NSString *const FIRCLSConfigureEndpoint; +FOUNDATION_EXPORT NSString *const FIRCLSReportsEndpoint; + +// Network requests +FOUNDATION_EXPORT NSString *const FIRCLSNetworkAccept; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkAcceptCharset; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkApplicationJson; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkAcceptLanguage; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkContentLanguage; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsAPIClientDisplayVersion; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsAPIClientId; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsDeveloperToken; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsGoogleAppId; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkCrashlyticsOrgId; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkUserAgent; +FOUNDATION_EXPORT NSString *const FIRCLSNetworkUTF8; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.m new file mode 100644 index 00000000..e9f58760 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSConstants.m @@ -0,0 +1,49 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSConstants.h" + +#define STR_HELPER(x) #x +#define STR(x) STR_HELPER(x) + +NSString* const FIRCLSDeveloperToken = @"77f0789d8e230eccdb4b99b82dccd78d47f9b604"; + +NSString* const FIRCLSVersion = @STR(DISPLAY_VERSION); + +// User Messages +NSString* const FIRCLSMissingConsumerKeyMsg = @"consumer key is nil or zero length"; +NSString* const FIRCLSMissingConsumerSecretMsg = @"consumer secret is nil or zero length"; + +// Exceptions +NSString* const FIRCLSException = @"FIRCLSException"; + +// Endpoints +NSString* const FIRCLSSettingsEndpoint = @"https://firebase-settings.crashlytics.com"; +NSString* const FIRCLSConfigureEndpoint = @"https://update.crashlytics.com"; +NSString* const FIRCLSReportsEndpoint = @"https://reports.crashlytics.com"; + +// Network requests +NSString* const FIRCLSNetworkAccept = @"Accept"; +NSString* const FIRCLSNetworkAcceptCharset = @"Accept-Charset"; +NSString* const FIRCLSNetworkApplicationJson = @"application/json"; +NSString* const FIRCLSNetworkAcceptLanguage = @"Accept-Language"; +NSString* const FIRCLSNetworkContentLanguage = @"Content-Language"; +NSString* const FIRCLSNetworkCrashlyticsAPIClientDisplayVersion = + @"X-Crashlytics-API-Client-Display-Version"; +NSString* const FIRCLSNetworkCrashlyticsAPIClientId = @"X-Crashlytics-API-Client-Id"; +NSString* const FIRCLSNetworkCrashlyticsDeveloperToken = @"X-Crashlytics-Developer-Token"; +NSString* const FIRCLSNetworkCrashlyticsGoogleAppId = @"X-Crashlytics-Google-App-Id"; +NSString* const FIRCLSNetworkCrashlyticsOrgId = @"X-Crashlytics-Org-Id"; +NSString* const FIRCLSNetworkUserAgent = @"User-Agent"; +NSString* const FIRCLSNetworkUTF8 = @"utf-8"; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h new file mode 100644 index 00000000..82c8fccf --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.h @@ -0,0 +1,35 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +/** + * Returns the OS version of the host device + */ +NSOperatingSystemVersion FIRCLSHostGetOSVersion(void); + +/** + * Returns model info for the device on which app is running + */ +NSString *FIRCLSHostModelInfo(void); + +/** + * Returns a string representing the OS build + */ +NSString *FIRCLSHostOSBuildVersion(void); + +/** + * Returns a concatenated string of the OS version(majorVersion.minorVersion.patchVersion) + */ +NSString *FIRCLSHostOSDisplayVersion(void); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.m new file mode 100644 index 00000000..c3d53e9a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSFABHost.m @@ -0,0 +1,119 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Shared/FIRCLSFABHost.h" + +#if TARGET_OS_WATCH +#import <WatchKit/WatchKit.h> +#elif TARGET_OS_IPHONE +#import <UIKit/UIKit.h> +#endif + +#include <sys/sysctl.h> + +#define FIRCLS_HOST_SYSCTL_BUFFER_SIZE (128) + +#pragma mark - OS Versions + +#pragma mark Private + +static NSString *FIRCLSHostSysctlEntry(const char *sysctlKey) { + char buffer[FIRCLS_HOST_SYSCTL_BUFFER_SIZE]; + size_t bufferSize = FIRCLS_HOST_SYSCTL_BUFFER_SIZE; + if (sysctlbyname(sysctlKey, buffer, &bufferSize, NULL, 0) != 0) { + return nil; + } + return [NSString stringWithUTF8String:buffer]; +} + +#pragma mark Public + +NSOperatingSystemVersion FIRCLSHostGetOSVersion(void) { + // works on macos(10.10), ios(8.0), watchos(2.0), tvos(9.0) + if ([NSProcessInfo.processInfo respondsToSelector:@selector(operatingSystemVersion)]) { + return [NSProcessInfo.processInfo operatingSystemVersion]; + } + + NSOperatingSystemVersion version = {0, 0, 0}; + +#if TARGET_OS_IPHONE + +#if TARGET_OS_WATCH + NSString *versionString = [[WKInterfaceDevice currentDevice] systemVersion]; +#else + NSString *versionString = [[UIDevice currentDevice] systemVersion]; +#endif + + NSArray *parts = [versionString componentsSeparatedByString:@"."]; + + if (parts.count > 0) { + version.majorVersion = [[parts objectAtIndex:0] integerValue]; + } + + if ([parts count] > 1) { + version.minorVersion = [[parts objectAtIndex:1] integerValue]; + } + + if ([parts count] > 2) { + version.patchVersion = [[parts objectAtIndex:2] integerValue]; + } + +#endif + + return version; +} + +NSString *FIRCLSHostOSBuildVersion(void) { + return FIRCLSHostSysctlEntry("kern.osversion"); +} + +NSString *FIRCLSHostOSDisplayVersion(void) { + NSOperatingSystemVersion version = FIRCLSHostGetOSVersion(); + return [NSString stringWithFormat:@"%ld.%ld.%ld", (long)version.majorVersion, + (long)version.minorVersion, (long)version.patchVersion]; +} + +#pragma mark - Host Models + +#pragma mark Public + +NSString *FIRCLSHostModelInfo(void) { + NSString *model = nil; + +#if TARGET_OS_SIMULATOR +#if TARGET_OS_WATCH + model = @"watchOS Simulator"; +#elif TARGET_OS_TV + model = @"tvOS Simulator"; +#elif TARGET_OS_IPHONE + switch (UI_USER_INTERFACE_IDIOM()) { + case UIUserInterfaceIdiomPhone: + model = @"iOS Simulator (iPhone)"; + break; + case UIUserInterfaceIdiomPad: + model = @"iOS Simulator (iPad)"; + break; + default: + model = @"iOS Simulator (Unknown)"; + break; + } +#endif +#elif TARGET_OS_EMBEDDED + model = FIRCLSHostSysctlEntry("hw.machine"); +#else + model = FIRCLSHostSysctlEntry("hw.model"); +#endif + + return model; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h new file mode 100644 index 00000000..ae80c46a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h @@ -0,0 +1,34 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +typedef enum { + FIRCLSCodeMappingSourceUnknown, + FIRCLSCodeMappingSourceBuild, + FIRCLSCodeSourceCache, + FIRCLSCodeSourceSpotlight +} FIRCLSCodeMappingSource; + +@interface FIRCLSCodeMapping : NSObject + ++ (instancetype)mappingWithURL:(NSURL*)URL; + +- (instancetype)initWithURL:(NSURL*)URL; + +@property(nonatomic, copy, readonly) NSURL* URL; +@property(nonatomic, assign) FIRCLSCodeMappingSource source; +@property(nonatomic, copy, readonly) NSString* sourceName; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.m new file mode 100644 index 00000000..4ce891f5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.m @@ -0,0 +1,40 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSCodeMapping.h" + +@interface FIRCLSCodeMapping () { + FIRCLSCodeMappingSource _source; +} + +@end + +@implementation FIRCLSCodeMapping + ++ (instancetype)mappingWithURL:(NSURL*)URL { + return [[self alloc] initWithURL:URL]; +} + +- (instancetype)initWithURL:(NSURL*)URL { + self = [super init]; + if (!self) { + return nil; + } + + _URL = [URL copy]; + + return self; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h new file mode 100644 index 00000000..59b46055 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h @@ -0,0 +1,110 @@ +// Copyright 2019 Google +// +// 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. + +#pragma once + +#include <mach-o/arch.h> +#include <mach-o/loader.h> +#include <sys/types.h> + +#include <CoreFoundation/CoreFoundation.h> + +struct FIRCLSMachOFile { + int fd; + size_t mappedSize; + void* mappedFile; +}; +typedef struct FIRCLSMachOFile* FIRCLSMachOFileRef; + +struct FIRCLSMachOSlice { + const void* startAddress; + cpu_type_t cputype; + cpu_subtype_t cpusubtype; +}; +typedef struct FIRCLSMachOSlice* FIRCLSMachOSliceRef; + +typedef struct { + uint32_t major; + uint32_t minor; + uint32_t bugfix; +} FIRCLSMachOVersion; + +typedef struct { + uint64_t addr; + uint64_t size; + uint32_t offset; +} FIRCLSMachOSection; + +typedef struct { + char segname[16]; + uint64_t vmaddr; + uint64_t vmsize; +} FIRCLSMachOSegmentCommand; + +typedef void (^FIRCLSMachOSliceIterator)(FIRCLSMachOSliceRef slice); +typedef void (^FIRCLSMachOLoadCommandIterator)(uint32_t type, + uint32_t size, + const struct load_command* cmd); + +__BEGIN_DECLS + +bool FIRCLSMachOFileInitWithPath(FIRCLSMachOFileRef file, const char* path); +bool FIRCLSMachOFileInitWithCurrent(FIRCLSMachOFileRef file); +void FIRCLSMachOFileDestroy(FIRCLSMachOFileRef file); +void FIRCLSMachOFileEnumerateSlices(FIRCLSMachOFileRef file, FIRCLSMachOSliceIterator block); +struct FIRCLSMachOSlice FIRCLSMachOFileSliceWithArchitectureName(FIRCLSMachOFileRef file, + const char* name); + +void FIRCLSMachOEnumerateSlicesAtAddress(void* executableData, FIRCLSMachOSliceIterator block); +void FIRCLSMachOSliceEnumerateLoadCommands(FIRCLSMachOSliceRef slice, + FIRCLSMachOLoadCommandIterator block); +struct FIRCLSMachOSlice FIRCLSMachOSliceGetCurrent(void); +struct FIRCLSMachOSlice FIRCLSMachOSliceWithHeader(void* machHeader); + +const char* FIRCLSMachOSliceGetExecutablePath(FIRCLSMachOSliceRef slice); +const char* FIRCLSMachOSliceGetArchitectureName(FIRCLSMachOSliceRef slice); +bool FIRCLSMachOSliceIs64Bit(FIRCLSMachOSliceRef slice); +bool FIRCLSMachOSliceGetSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + const void** ptr); +bool FIRCLSMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + FIRCLSMachOSection* section); +void FIRCLSMachOSliceGetUnwindInformation(FIRCLSMachOSliceRef slice, + const void** ehFrame, + const void** unwindInfo); + +// load-command-specific calls for convenience + +// returns a pointer to the 16-byte UUID +uint8_t const* FIRCLSMachOGetUUID(const struct load_command* cmd); +const char* FIRCLSMachOGetDylibPath(const struct load_command* cmd); + +// return true if the header indicates the binary is encrypted +bool FIRCLSMachOGetEncrypted(const struct load_command* cmd); + +// SDK minimums +FIRCLSMachOVersion FIRCLSMachOGetMinimumOSVersion(const struct load_command* cmd); +FIRCLSMachOVersion FIRCLSMachOGetLinkedSDKVersion(const struct load_command* cmd); + +// Helpers +FIRCLSMachOSegmentCommand FIRCLSMachOGetSegmentCommand(const struct load_command* cmd); + +#ifdef __OBJC__ +NSString* FIRCLSMachONormalizeUUID(CFUUIDBytes* uuidBytes); +NSString* FIRCLSMachOFormatVersion(FIRCLSMachOVersion* version); +#endif +__END_DECLS diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.m new file mode 100644 index 00000000..9991121d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.m @@ -0,0 +1,509 @@ +// Copyright 2019 Google +// +// 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. + +#include "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" + +#include <Foundation/Foundation.h> + +#include <mach-o/dyld.h> +#include <mach-o/fat.h> +#include <mach-o/getsect.h> +#include <mach-o/ldsyms.h> + +#include <sys/mman.h> +#include <sys/stat.h> + +#include <dlfcn.h> +#include <fcntl.h> + +#include <stdio.h> + +#include <unistd.h> + +// This is defined in newer versions of iOS/macOS in usr/include/mach/machine.h +#define CLS_CPU_SUBTYPE_ARM64E ((cpu_subtype_t)2) + +static void FIRCLSMachOHeaderValues(FIRCLSMachOSliceRef slice, + const struct load_command** cmds, + uint32_t* cmdCount); +static bool FIRCLSMachOSliceIsValid(FIRCLSMachOSliceRef slice); + +bool FIRCLSMachOFileInitWithPath(FIRCLSMachOFileRef file, const char* path) { + struct stat statBuffer; + + if (!file || !path) { + return false; + } + + file->fd = 0; + file->mappedFile = NULL; + file->mappedSize = 0; + + file->fd = open(path, O_RDONLY); + if (file->fd < 0) { + // unable to open mach-o file + return false; + } + + if (fstat(file->fd, &statBuffer) == -1) { + close(file->fd); + return false; + } + + // We need some minimum size for this to even be a possible mach-o file. I believe + // its probably quite a bit bigger than this, but this at least covers something. + // We also need it to be a regular file. + file->mappedSize = (size_t)statBuffer.st_size; + if (statBuffer.st_size < 16 || !(statBuffer.st_mode & S_IFREG)) { + close(file->fd); + return false; + } + + // Map the file to memory. MAP_SHARED can potentially reduce the amount of actual private + // memory needed to do this mapping. Also, be sure to check for the correct failure result. + file->mappedFile = mmap(0, file->mappedSize, PROT_READ, MAP_FILE | MAP_SHARED, file->fd, 0); + if (!file->mappedFile || (file->mappedFile == MAP_FAILED)) { + close(file->fd); + return false; + } + + return true; +} + +bool FIRCLSMachOFileInitWithCurrent(FIRCLSMachOFileRef file) { + struct FIRCLSMachOSlice slice = FIRCLSMachOSliceGetCurrent(); + + const char* imagePath = FIRCLSMachOSliceGetExecutablePath(&slice); + + return FIRCLSMachOFileInitWithPath(file, imagePath); +} + +void FIRCLSMachOFileDestroy(FIRCLSMachOFileRef file) { + if (!file) { + return; + } + + if (file->mappedFile && file->mappedSize > 0) { + munmap(file->mappedFile, file->mappedSize); + } + + close(file->fd); +} + +void FIRCLSMachOFileEnumerateSlices(FIRCLSMachOFileRef file, FIRCLSMachOSliceIterator block) { + FIRCLSMachOEnumerateSlicesAtAddress(file->mappedFile, block); +} + +void FIRCLSMachOEnumerateSlicesAtAddress(void* executableData, FIRCLSMachOSliceIterator block) { + // check the magic value, to determine if we have a fat header or not + uint32_t magicValue; + uint32_t archCount; + const struct fat_arch* fatArch; + struct FIRCLSMachOSlice slice; + + memset(&slice, 0, sizeof(struct FIRCLSMachOSlice)); + + magicValue = ((struct fat_header*)executableData)->magic; + if ((magicValue != FAT_MAGIC) && (magicValue != FAT_CIGAM)) { + slice.startAddress = executableData; + + // use this to fill in the values + FIRCLSMachOHeaderValues(&slice, NULL, NULL); + + block(&slice); + + return; + } + + archCount = OSSwapBigToHostInt32(((struct fat_header*)executableData)->nfat_arch); + fatArch = executableData + sizeof(struct fat_header); + + for (uint32_t i = 0; i < archCount; ++i) { + slice.cputype = OSSwapBigToHostInt32(fatArch->cputype); + slice.cpusubtype = OSSwapBigToHostInt32(fatArch->cpusubtype); + slice.startAddress = executableData + OSSwapBigToHostInt32(fatArch->offset); + + block(&slice); + + // advance to the next fat_arch structure + fatArch = (struct fat_arch*)((uintptr_t)fatArch + sizeof(struct fat_arch)); + } +} + +struct FIRCLSMachOSlice FIRCLSMachOFileSliceWithArchitectureName(FIRCLSMachOFileRef file, + const char* name) { + __block struct FIRCLSMachOSlice value; + + memset(&value, 0, sizeof(struct FIRCLSMachOSlice)); + + FIRCLSMachOFileEnumerateSlices(file, ^(FIRCLSMachOSliceRef slice) { + if (strcmp(FIRCLSMachOSliceGetArchitectureName(slice), name) == 0) { + value = *slice; + } + }); + + return value; +} + +static void FIRCLSMachOHeaderValues(FIRCLSMachOSliceRef slice, + const struct load_command** cmds, + uint32_t* cmdCount) { + const struct mach_header* header32 = (const struct mach_header*)slice->startAddress; + const struct mach_header_64* header64 = (const struct mach_header_64*)slice->startAddress; + uint32_t commandCount; + const void* commandsAddress; + + if (cmds) { + *cmds = NULL; + } + + if (cmdCount) { + *cmdCount = 0; + } + + if (!slice->startAddress) { + return; + } + + // the 32 and 64 bit versions have an identical structures, so this will work + switch (header32->magic) { + case MH_MAGIC: // 32-bit + case MH_CIGAM: + slice->cputype = header32->cputype; + slice->cpusubtype = header32->cpusubtype; + commandCount = header32->ncmds; + commandsAddress = slice->startAddress + sizeof(struct mach_header); + break; + case MH_MAGIC_64: // 64-bit + case MH_CIGAM_64: + slice->cputype = header64->cputype; + slice->cpusubtype = header64->cpusubtype; + commandCount = header64->ncmds; + commandsAddress = slice->startAddress + sizeof(struct mach_header_64); + break; + default: + // not a valid header + return; + } + + // assign everything back by reference + if (cmds) { + *cmds = commandsAddress; + } + + if (cmdCount) { + *cmdCount = commandCount; + } +} + +static bool FIRCLSMachOSliceIsValid(FIRCLSMachOSliceRef slice) { + if (!slice) { + return false; + } + + if (!slice->startAddress) { + return false; + } + + return true; +} + +void FIRCLSMachOSliceEnumerateLoadCommands(FIRCLSMachOSliceRef slice, + FIRCLSMachOLoadCommandIterator block) { + const struct load_command* cmd; + uint32_t cmdCount; + + if (!block) { + return; + } + + if (!FIRCLSMachOSliceIsValid(slice)) { + return; + } + + FIRCLSMachOHeaderValues(slice, &cmd, &cmdCount); + + for (uint32_t i = 0; cmd != NULL && i < cmdCount; ++i) { + block(cmd->cmd, cmd->cmdsize, cmd); + + cmd = (struct load_command*)((uintptr_t)cmd + cmd->cmdsize); + } +} + +struct FIRCLSMachOSlice FIRCLSMachOSliceGetCurrent(void) { + const NXArchInfo* archInfo; + struct FIRCLSMachOSlice slice; + void* executableSymbol; + Dl_info dlinfo; + + archInfo = NXGetLocalArchInfo(); + if (archInfo) { + slice.cputype = archInfo->cputype; + slice.cpusubtype = archInfo->cpusubtype; + } + + slice.startAddress = NULL; + + // This call can fail when Exported Symbols File in Build Settings is missing the symbol value + // defined as _MH_EXECUTE_SYM (if you look in the header the underscored MH_EXECUTE_SYM define is + // there) + executableSymbol = dlsym(RTLD_MAIN_ONLY, MH_EXECUTE_SYM); + + // get the address of the main function + if (dladdr(executableSymbol, &dlinfo) != 0) { + slice.startAddress = dlinfo.dli_fbase; + } + + return slice; +} + +struct FIRCLSMachOSlice FIRCLSMachOSliceWithHeader(void* machHeader) { + struct FIRCLSMachOSlice slice; + + slice.startAddress = machHeader; + + return slice; +} + +const char* FIRCLSMachOSliceGetExecutablePath(FIRCLSMachOSliceRef slice) { + Dl_info info; + + if (!FIRCLSMachOSliceIsValid(slice)) { + return NULL; + } + + // use dladdr here to look up the information we need for a binary image + if (dladdr(slice->startAddress, &info) == 0) { + return NULL; + } + + return info.dli_fname; +} + +const char* FIRCLSMachOSliceGetArchitectureName(FIRCLSMachOSliceRef slice) { + const NXArchInfo* archInfo; + + // there are some special cases here for types not handled by earlier OSes + if (slice->cputype == CPU_TYPE_ARM && slice->cpusubtype == CPU_SUBTYPE_ARM_V7S) { + return "armv7s"; + } + + if (slice->cputype == (CPU_TYPE_ARM | CPU_ARCH_ABI64)) { + if (slice->cpusubtype == CLS_CPU_SUBTYPE_ARM64E) { + return "arm64e"; + } else if (slice->cpusubtype == CPU_SUBTYPE_ARM64_ALL) { + return "arm64"; + } + } + + if (slice->cputype == (CPU_TYPE_ARM) && slice->cpusubtype == CPU_SUBTYPE_ARM_V7K) { + return "armv7k"; + } + + archInfo = NXGetArchInfoFromCpuType(slice->cputype, slice->cpusubtype); + if (!archInfo) { + return "unknown"; + } + + return archInfo->name; +} + +bool FIRCLSMachOSliceIs64Bit(FIRCLSMachOSliceRef slice) { + // I'm pretty sure this is sufficient... + return (slice->cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64; +} + +bool FIRCLSMachOSliceGetSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + const void** ptr) { + if (!ptr) { + return false; + } + + *ptr = NULL; // make sure this is set before returning + + FIRCLSMachOSection section; + + if (!FIRCLSMachOSliceInitSectionByName(slice, segName, sectionName, §ion)) { + return false; + } + + // WARNING: this calculation isn't correct, but is here to maintain backwards + // compatibility for now with callers of FIRCLSMachOSliceGetSectionByName. All new + // users should be calling FIRCLSMachOSliceInitSectionByName + *ptr = (const void*)((uintptr_t)slice->startAddress + section.offset); + + return true; +} + +bool FIRCLSMachOSliceInitSectionByName(FIRCLSMachOSliceRef slice, + const char* segName, + const char* sectionName, + FIRCLSMachOSection* section) { + if (!FIRCLSMachOSliceIsValid(slice)) { + return false; + } + + if (!section) { + return false; + } + + memset(section, 0, sizeof(FIRCLSMachOSection)); + + if (FIRCLSMachOSliceIs64Bit(slice)) { + const struct section_64* sect = + getsectbynamefromheader_64(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } else { + const struct section* sect = getsectbynamefromheader(slice->startAddress, segName, sectionName); + if (!sect) { + return false; + } + + section->addr = sect->addr; + section->size = sect->size; + section->offset = sect->offset; + } + + return true; +} + +// TODO: this is left in-place just to ensure that old crashltyics + new fabric are still compatible +// with each other. As a happy bonus, if that situation does come up, this will also fix the bug +// that was preventing compact unwind on arm64 + iOS 9 from working correctly. +void FIRCLSMachOSliceGetUnwindInformation(FIRCLSMachOSliceRef slice, + const void** ehFrame, + const void** unwindInfo) { + if (!unwindInfo && !ehFrame) { + return; + } + + bool found = false; + intptr_t slide = 0; + + // This is inefficient, but we have no other safe way to do this correctly. Modifying the + // FIRCLSMachOSlice structure is tempting, but could introduce weird binary-compatibility issues + // with version mis-matches. + for (uint32_t i = 0; i < _dyld_image_count(); ++i) { + const struct mach_header* header = _dyld_get_image_header(i); + + if (header == slice->startAddress) { + found = true; + slide = _dyld_get_image_vmaddr_slide(i); + break; + } + } + + // make sure we were able to find a matching value + if (!found) { + return; + } + + FIRCLSMachOSection section; + + if (unwindInfo) { + if (FIRCLSMachOSliceInitSectionByName(slice, SEG_TEXT, "__unwind_info", §ion)) { + *unwindInfo = (void*)(section.addr + slide); + } + } + + if (ehFrame) { + if (FIRCLSMachOSliceInitSectionByName(slice, SEG_TEXT, "__eh_frame", §ion)) { + *ehFrame = (void*)(section.addr + slide); + } + } +} + +uint8_t const* FIRCLSMachOGetUUID(const struct load_command* cmd) { + return ((const struct uuid_command*)cmd)->uuid; +} + +const char* FIRCLSMachOGetDylibPath(const struct load_command* cmd) { + const struct dylib_command* dylibcmd = (const struct dylib_command*)cmd; + + return (const char*)((uintptr_t)cmd + dylibcmd->dylib.name.offset); +} + +bool FIRCLSMachOGetEncrypted(const struct load_command* cmd) { + return ((struct encryption_info_command*)cmd)->cryptid > 0; +} + +static FIRCLSMachOVersion FIRCLSMachOVersionFromEncoded(uint32_t encoded) { + FIRCLSMachOVersion version; + + version.major = (encoded & 0xffff0000) >> 16; + version.minor = (encoded & 0x0000ff00) >> 8; + version.bugfix = encoded & 0x000000ff; + + return version; +} + +FIRCLSMachOVersion FIRCLSMachOGetMinimumOSVersion(const struct load_command* cmd) { + return FIRCLSMachOVersionFromEncoded(((const struct version_min_command*)cmd)->version); +} + +FIRCLSMachOVersion FIRCLSMachOGetLinkedSDKVersion(const struct load_command* cmd) { + return FIRCLSMachOVersionFromEncoded(((const struct version_min_command*)cmd)->sdk); +} + +FIRCLSMachOSegmentCommand FIRCLSMachOGetSegmentCommand(const struct load_command* cmd) { + FIRCLSMachOSegmentCommand segmentCommand; + + memset(&segmentCommand, 0, sizeof(FIRCLSMachOSegmentCommand)); + + if (!cmd) { + return segmentCommand; + } + + if (cmd->cmd == LC_SEGMENT) { + struct segment_command* segCmd = (struct segment_command*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } else if (cmd->cmd == LC_SEGMENT_64) { + struct segment_command_64* segCmd = (struct segment_command_64*)cmd; + + memcpy(segmentCommand.segname, segCmd->segname, 16); + segmentCommand.vmaddr = segCmd->vmaddr; + segmentCommand.vmsize = segCmd->vmsize; + } + + return segmentCommand; +} + +NSString* FIRCLSMachONormalizeUUID(CFUUIDBytes* uuidBytes) { + CFUUIDRef uuid = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, *uuidBytes); + + NSString* string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + + CFRelease(uuid); + + return [[string stringByReplacingOccurrencesOfString:@"-" withString:@""] lowercaseString]; +} + +NSString* FIRCLSMachOFormatVersion(FIRCLSMachOVersion* version) { + if (!version) { + return nil; + } + + return [NSString stringWithFormat:@"%d.%d.%d", version->major, version->minor, version->bugfix]; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h new file mode 100644 index 00000000..94c7fa86 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h @@ -0,0 +1,41 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" + +@class FIRCLSMachOSlice; + +@interface FIRCLSMachOBinary : NSObject { + NSURL* _url; + + struct FIRCLSMachOFile _file; + NSMutableArray* _slices; + NSString* _instanceIdentifier; +} + ++ (id)MachOBinaryWithPath:(NSString*)path; + +- (id)initWithURL:(NSURL*)url; + +@property(nonatomic, copy, readonly) NSURL* URL; +@property(nonatomic, copy, readonly) NSString* path; +@property(nonatomic, strong, readonly) NSArray* slices; +@property(nonatomic, copy, readonly) NSString* instanceIdentifier; + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block; + +- (FIRCLSMachOSlice*)sliceForArchitecture:(NSString*)architecture; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.m new file mode 100644 index 00000000..02e9125a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.m @@ -0,0 +1,175 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h" + +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h" + +#import <CommonCrypto/CommonHMAC.h> + +static void FIRCLSSafeHexToString(const uint8_t* value, size_t length, char* outputBuffer); +static NSString* FIRCLSNSDataToNSString(NSData* data); +static NSString* FIRCLSHashBytes(const void* bytes, size_t length); +static NSString* FIRCLSHashNSString(NSString* value); + +@interface FIRCLSMachOBinary () + ++ (NSString*)hashNSString:(NSString*)value; + +@end + +@implementation FIRCLSMachOBinary + ++ (id)MachOBinaryWithPath:(NSString*)path { + return [[self alloc] initWithURL:[NSURL fileURLWithPath:path]]; +} + +@synthesize slices = _slices; + +- (id)initWithURL:(NSURL*)url { + self = [super init]; + if (self) { + _url = [url copy]; + + if (!FIRCLSMachOFileInitWithPath(&_file, [[_url path] fileSystemRepresentation])) { + return nil; + } + + _slices = [NSMutableArray new]; + FIRCLSMachOFileEnumerateSlices(&_file, ^(FIRCLSMachOSliceRef slice) { + FIRCLSMachOSlice* sliceObject; + + sliceObject = [[FIRCLSMachOSlice alloc] initWithSlice:slice]; + + [self->_slices addObject:sliceObject]; + }); + } + + return self; +} + +- (void)dealloc { + FIRCLSMachOFileDestroy(&_file); +} + +- (NSURL*)URL { + return _url; +} + +- (NSString*)path { + return [_url path]; +} + +- (NSString*)instanceIdentifier { + if (_instanceIdentifier) { + return _instanceIdentifier; + } + + NSMutableString* prehashedString = [NSMutableString new]; + + // sort the slices by architecture + NSArray* sortedSlices = + [_slices sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { + return [[obj1 architectureName] compare:[obj2 architectureName]]; + }]; + + // append them all into a big string + for (FIRCLSMachOSlice* slice in sortedSlices) { + [prehashedString appendString:[slice uuid]]; + } + + _instanceIdentifier = [FIRCLSHashNSString(prehashedString) copy]; + + return _instanceIdentifier; +} + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block { + for (FIRCLSMachOSlice* slice in _slices) { + block([slice uuid], [slice architectureName]); + } +} + +- (FIRCLSMachOSlice*)sliceForArchitecture:(NSString*)architecture { + for (FIRCLSMachOSlice* slice in [self slices]) { + if ([[slice architectureName] isEqualToString:architecture]) { + return slice; + } + } + + return nil; +} + ++ (NSString*)hashNSString:(NSString*)value { + return FIRCLSHashNSString(value); +} + +@end + +// TODO: Functions copied from the SDK. We should figure out a way to share this. +static void FIRCLSSafeHexToString(const uint8_t* value, size_t length, char* outputBuffer) { + const char hex[] = "0123456789abcdef"; + + if (!value) { + outputBuffer[0] = '\0'; + return; + } + + for (size_t i = 0; i < length; ++i) { + unsigned char c = value[i]; + outputBuffer[i * 2] = hex[c >> 4]; + outputBuffer[i * 2 + 1] = hex[c & 0x0F]; + } + + outputBuffer[length * 2] = '\0'; // null terminate +} + +static NSString* FIRCLSNSDataToNSString(NSData* data) { + NSString* string; + char* buffer; + size_t size; + NSUInteger length; + + // we need 2 hex char for every byte of data, plus one more spot for a + // null terminator + length = [data length]; + size = (length * 2) + 1; + buffer = malloc(sizeof(char) * size); + + if (!buffer) { + return nil; + } + + FIRCLSSafeHexToString([data bytes], length, buffer); + + string = [NSString stringWithUTF8String:buffer]; + + free(buffer); + + return string; +} + +static NSString* FIRCLSHashBytes(const void* bytes, size_t length) { + uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; + CC_SHA1(bytes, (CC_LONG)length, digest); + + NSData* result = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; + + return FIRCLSNSDataToNSString(result); +} + +static NSString* FIRCLSHashNSString(NSString* value) { + const char* s = [value cStringUsingEncoding:NSUTF8StringEncoding]; + + return FIRCLSHashBytes(s, strlen(s)); +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h new file mode 100644 index 00000000..eb55ed97 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h @@ -0,0 +1,37 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachO.h" + +@interface FIRCLSMachOSlice : NSObject { + struct FIRCLSMachOSlice _slice; + + NSString* _uuidString; + NSArray* _linkedDylibs; + FIRCLSMachOVersion _minimumOSVersion; + FIRCLSMachOVersion _linkedSDKVersion; +} + ++ (id)runningSlice; + +- (id)initWithSlice:(FIRCLSMachOSliceRef)sliceRef; + +@property(nonatomic, copy, readonly) NSString* uuid; +@property(nonatomic, copy, readonly) NSString* architectureName; +@property(nonatomic, strong, readonly) NSArray* linkedDylibs; +@property(nonatomic, assign, readonly) FIRCLSMachOVersion minimumOSVersion; +@property(nonatomic, assign, readonly) FIRCLSMachOVersion linkedSDKVersion; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.m new file mode 100644 index 00000000..d28626b8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.m @@ -0,0 +1,93 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOSlice.h" + +#include <mach-o/loader.h> + +// this is defined only if __OPEN_SOURCE__ is *not* defined in the TVOS SDK's mach-o/loader.h +// also, it has not yet made it back to the OSX SDKs, for example +#ifndef LC_VERSION_MIN_TVOS +#define LC_VERSION_MIN_TVOS 0x2F +#endif + +@implementation FIRCLSMachOSlice + ++ (id)runningSlice { + struct FIRCLSMachOSlice slice; + + slice = FIRCLSMachOSliceGetCurrent(); + + return [[self alloc] initWithSlice:&slice]; +} + +@synthesize minimumOSVersion = _minimumOSVersion; +@synthesize linkedSDKVersion = _linkedSDKVersion; + +- (id)initWithSlice:(FIRCLSMachOSliceRef)sliceRef { + self = [super init]; + if (self) { + NSMutableArray* dylibs; + + _slice = *sliceRef; + + _minimumOSVersion.major = 0; + _minimumOSVersion.minor = 0; + _minimumOSVersion.bugfix = 0; + + _linkedSDKVersion.major = 0; + _linkedSDKVersion.minor = 0; + _linkedSDKVersion.bugfix = 0; + + dylibs = [NSMutableArray array]; + + FIRCLSMachOSliceEnumerateLoadCommands( + &_slice, ^(uint32_t type, uint32_t size, const struct load_command* cmd) { + switch (type) { + case LC_UUID: + self->_uuidString = + [FIRCLSMachONormalizeUUID((CFUUIDBytes*)FIRCLSMachOGetUUID(cmd)) copy]; + break; + case LC_LOAD_DYLIB: + [dylibs addObject:[NSString stringWithUTF8String:FIRCLSMachOGetDylibPath(cmd)]]; + break; + case LC_VERSION_MIN_IPHONEOS: + case LC_VERSION_MIN_MACOSX: + case LC_VERSION_MIN_WATCHOS: + case LC_VERSION_MIN_TVOS: + self->_minimumOSVersion = FIRCLSMachOGetMinimumOSVersion(cmd); + self->_linkedSDKVersion = FIRCLSMachOGetLinkedSDKVersion(cmd); + break; + } + }); + + _linkedDylibs = [dylibs copy]; + } + + return self; +} + +- (NSString*)architectureName { + return [NSString stringWithUTF8String:FIRCLSMachOSliceGetArchitectureName(&_slice)]; +} + +- (NSString*)uuid { + return _uuidString; +} + +- (NSArray*)linkedDylibs { + return _linkedDylibs; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h new file mode 100644 index 00000000..c80ac745 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h @@ -0,0 +1,38 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +@class FIRCLSMachOBinary; + +@interface FIRCLSdSYM : NSObject + +NS_ASSUME_NONNULL_BEGIN + ++ (id)dSYMWithURL:(NSURL*)url; + +- (id)initWithURL:(NSURL*)url; + +@property(nonatomic, readonly) FIRCLSMachOBinary* binary; +@property(nonatomic, copy, readonly, nullable) NSString* bundleIdentifier; +@property(nonatomic, copy, readonly) NSURL* executableURL; +@property(nonatomic, copy, readonly) NSString* executablePath; +@property(nonatomic, copy, readonly) NSString* bundleVersion; +@property(nonatomic, copy, readonly) NSString* shortBundleVersion; + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block; + +NS_ASSUME_NONNULL_END + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.m new file mode 100644 index 00000000..393e9a58 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.m @@ -0,0 +1,109 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSdSYM.h" + +#import "Crashlytics/Shared/FIRCLSMachO/FIRCLSMachOBinary.h" + +#define CLS_XCODE_DSYM_PREFIX (@"com.apple.xcode.dsym.") + +@interface FIRCLSdSYM () + +@property(nonatomic, readonly) NSBundle* bundle; + +@end + +@implementation FIRCLSdSYM + ++ (id)dSYMWithURL:(NSURL*)url { + return [[self alloc] initWithURL:url]; +} + +- (id)initWithURL:(NSURL*)url { + self = [super init]; + if (self) { + NSDirectoryEnumerator* enumerator; + NSString* path; + NSFileManager* fileManager; + BOOL isDirectory; + BOOL fileExistsAtPath; + NSArray* itemsInDWARFDir; + + fileManager = [NSFileManager defaultManager]; + + // Is there a file at this path? + if (![fileManager fileExistsAtPath:[url path]]) { + return nil; + } + + _bundle = [NSBundle bundleWithURL:url]; + if (!_bundle) { + return nil; + } + + path = [[url path] stringByAppendingPathComponent:@"Contents/Resources/DWARF"]; + + // Does this path exist and is it a directory? + fileExistsAtPath = [fileManager fileExistsAtPath:path isDirectory:&isDirectory]; + if (!fileExistsAtPath || !isDirectory) { + return nil; + } + + enumerator = [fileManager enumeratorAtPath:path]; + itemsInDWARFDir = [enumerator allObjects]; + // Do we have a Contents/Resources/DWARF dir but no contents? + if ([itemsInDWARFDir count] == 0) { + return nil; + } + + path = [path stringByAppendingPathComponent:[itemsInDWARFDir objectAtIndex:0]]; + + _binary = [[FIRCLSMachOBinary alloc] initWithURL:[NSURL fileURLWithPath:path]]; + } + + return self; +} + +- (NSString*)bundleIdentifier { + NSString* identifier; + + identifier = [_bundle bundleIdentifier]; + if ([identifier hasPrefix:CLS_XCODE_DSYM_PREFIX]) { + return [identifier substringFromIndex:[CLS_XCODE_DSYM_PREFIX length]]; + } + + return identifier; +} + +- (NSURL*)executableURL { + return [_binary URL]; +} + +- (NSString*)executablePath { + return [_binary path]; +} + +- (NSString*)bundleVersion { + return [[_bundle infoDictionary] objectForKey:@"CFBundleVersion"]; +} + +- (NSString*)shortBundleVersion { + return [[_bundle infoDictionary] objectForKey:@"CFBundleShortVersionString"]; +} + +- (void)enumerateUUIDs:(void (^)(NSString* uuid, NSString* architecture))block { + [_binary enumerateUUIDs:block]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h new file mode 100644 index 00000000..ebbd26c9 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h @@ -0,0 +1,56 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +OBJC_EXTERN const NSUInteger FIRCLSNetworkMaximumRetryCount; + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^FIRCLSNetworkDataTaskCompletionHandlerBlock)(NSData *__nullable data, + NSURLResponse *__nullable response, + NSError *__nullable error); +typedef void (^FIRCLSNetworkDownloadTaskCompletionHandlerBlock)(NSURL *__nullable location, + NSURLResponse *__nullable response, + NSError *__nullable error); + +@interface FIRCLSFABNetworkClient : NSObject + +- (instancetype)init; +- (instancetype)initWithQueue:(nullable NSOperationQueue *)operationQueue; +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)config + queue:(nullable NSOperationQueue *)operationQueue + NS_DESIGNATED_INITIALIZER; + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler; +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler; + +- (void)invalidateAndCancel; + +// Backwards compatibility (we cannot change an interface in Fabric Base that other kits rely on, +// since we have no control of versioning dependencies) +- (void)startDataTaskWithRequest:(NSURLRequest *)request + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler; +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.m new file mode 100644 index 00000000..39630bae --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.m @@ -0,0 +1,280 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSFABNetworkClient.h" + +#if FIRCLSURLSESSION_REQUIRED +#import "Crashlytics/Crashlytics/FIRCLSURLSession/FIRCLSURLSession.h" +#endif + +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h" + +static const float FIRCLSNetworkMinimumRetryJitter = 0.90f; +static const float FIRCLSNetworkMaximumRetryJitter = 1.10f; +const NSUInteger FIRCLSNetworkMaximumRetryCount = 10; + +@interface FIRCLSFABNetworkClient () <NSURLSessionDelegate, NSURLSessionTaskDelegate> + +@property(nonatomic, strong, readonly) NSURLSession *session; + +@end + +@implementation FIRCLSFABNetworkClient + +- (instancetype)init { + return [self initWithQueue:nil]; +} + +- (instancetype)initWithQueue:(nullable NSOperationQueue *)operationQueue { +#if !FIRCLSURLSESSION_REQUIRED + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; +#else + NSURLSessionConfiguration *config = [FIRCLSURLSessionConfiguration defaultSessionConfiguration]; +#endif + return [self initWithSessionConfiguration:config queue:operationQueue]; +} + +- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)config + queue:(nullable NSOperationQueue *)operationQueue { + self = [super init]; + if (!self) { + return nil; + } + +#if !FIRCLSURLSESSION_REQUIRED + _session = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:operationQueue]; +#else + _session = [FIRCLSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:operationQueue]; +#endif + if (!_session) { + return nil; + } + + return self; +} + +- (void)dealloc { + [_session finishTasksAndInvalidate]; +} + +#pragma mark - Delay Handling +- (double)randomDoubleWithMin:(double)min max:(double)max { + return min + ((max - min) * drand48()); +} + +- (double)generateRandomJitter { + return [self randomDoubleWithMin:FIRCLSNetworkMinimumRetryJitter + max:FIRCLSNetworkMaximumRetryJitter]; +} + +- (NSTimeInterval)computeDelayForResponse:(NSURLResponse *)response + withRetryCount:(NSUInteger)count { + NSTimeInterval initialValue = [FIRCLSNetworkResponseHandler retryValueForResponse:response]; + + // make sure count is > 0 + count = MAX(count, 1); + // make sure initialValue is >2 for exponential backoff to work reasonably with low count numbers + initialValue = MAX(initialValue, 2.0); + + const double jitter = [self generateRandomJitter]; + + return pow(initialValue, count) * jitter; // exponential backoff +} + +- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response + attempts:(NSUInteger)count + onQueue:(dispatch_queue_t)queue + block:(void (^)(void))block { + const NSTimeInterval delay = [self computeDelayForResponse:response withRetryCount:count]; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(delay * NSEC_PER_SEC)), queue, block); +} + +- (void)runAfterRetryValueFromResponse:(NSURLResponse *)response + attempts:(NSUInteger)count + block:(void (^)(void))block { + dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); + + [self runAfterRetryValueFromResponse:response attempts:count onQueue:queue block:block]; +} + +#pragma mark - Tasks + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + tries:(NSUInteger)tries + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler { + NSURLSessionTask *task = [self.session + dataTaskWithRequest:request + completionHandler:^(NSData *data, NSURLResponse *response, NSError *taskError) { + [FIRCLSNetworkResponseHandler + handleCompletedResponse:response + forOriginalRequest:request + error:taskError + block:^(BOOL retry, NSError *error) { + if (!retry) { + completionHandler(data, response, error); + return; + } + + if (tries >= retryLimit) { + NSDictionary *userInfo = @{ + @"retryLimit" : @(retryLimit), + NSURLErrorFailingURLStringErrorKey : request.URL + }; + completionHandler( + nil, nil, + [NSError + errorWithDomain:FIRCLSNetworkErrorDomain + code:FIRCLSNetworkErrorMaximumAttemptsReached + userInfo:userInfo]); + return; + } + + [self + runAfterRetryValueFromResponse:response + attempts:tries + block:^{ + [self + startDataTaskWithRequest: + request + retryLimit: + retryLimit + tries: + (tries + + 1) + completionHandler: + completionHandler]; + }]; + }]; + }]; + + [task resume]; + + if (!task) { + completionHandler(nil, nil, + [NSError errorWithDomain:FIRCLSNetworkErrorDomain + code:FIRCLSNetworkErrorFailedToStartOperation + userInfo:nil]); + } +} + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler { + [self startDataTaskWithRequest:request + retryLimit:retryLimit + tries:0 + completionHandler:completionHandler]; +} + +- (void)startDataTaskWithRequest:(NSURLRequest *)request + completionHandler:(FIRCLSNetworkDataTaskCompletionHandlerBlock)completionHandler { + [self startDataTaskWithRequest:request + retryLimit:FIRCLSNetworkMaximumRetryCount + completionHandler:completionHandler]; +} + +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + tries:(NSUInteger)tries + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler { + NSURLSessionTask *task = [self.session + downloadTaskWithRequest:request + completionHandler:^(NSURL *location, NSURLResponse *response, NSError *taskError) { + [FIRCLSNetworkResponseHandler + handleCompletedResponse:response + forOriginalRequest:request + error:taskError + block:^(BOOL retry, NSError *error) { + if (!retry) { + completionHandler(location, response, error); + return; + } + + if (tries >= retryLimit) { + NSDictionary *userInfo = @{ + @"retryLimit" : @(retryLimit), + NSURLErrorFailingURLStringErrorKey : request.URL + }; + completionHandler( + nil, nil, + [NSError + errorWithDomain:FIRCLSNetworkErrorDomain + code: + FIRCLSNetworkErrorMaximumAttemptsReached + userInfo:userInfo]); + return; + } + + [self + runAfterRetryValueFromResponse:response + attempts:tries + block:^{ + [self + startDownloadTaskWithRequest: + request + retryLimit: + retryLimit + tries: + (tries + + 1) + completionHandler: + completionHandler]; + }]; + }]; + }]; + + [task resume]; + + if (!task) { + completionHandler(nil, nil, + [NSError errorWithDomain:FIRCLSNetworkErrorDomain + code:FIRCLSNetworkErrorFailedToStartOperation + userInfo:nil]); + } +} + +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + retryLimit:(NSUInteger)retryLimit + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler { + [self startDownloadTaskWithRequest:request + retryLimit:retryLimit + tries:0 + completionHandler:completionHandler]; +} + +- (void)startDownloadTaskWithRequest:(NSURLRequest *)request + completionHandler: + (FIRCLSNetworkDownloadTaskCompletionHandlerBlock)completionHandler { + [self startDownloadTaskWithRequest:request + retryLimit:FIRCLSNetworkMaximumRetryCount + completionHandler:completionHandler]; +} + +- (void)invalidateAndCancel { + [self.session invalidateAndCancel]; +} + +#pragma mark - NSURLSession Delegate +- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error { +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h new file mode 100644 index 00000000..c3630a5b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h @@ -0,0 +1,88 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +/** + * This class is a helper class for generating Multipart requests, as described in + * http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html. In the case of multiple part messages, in + * which one or more different sets of data are combined in a single body, a "multipart" + * Content-Type field must appear in the entity's header. The body must then contain one or more + * "body parts," each preceded by an encapsulation boundary, and the last one followed by a closing + * boundary. Each part starts with an encapsulation boundary, and then contains a body part + * consisting of header area, a blank line, and a body area. + */ +@interface FIRCLSMultipartMimeStreamEncoder : NSObject + +/** + * Convenience class method to populate a NSMutableURLRequest with data from a block that takes an + * instance of this class as input. + */ ++ (void)populateRequest:(NSMutableURLRequest *)request + withDataFromEncoder:(void (^)(FIRCLSMultipartMimeStreamEncoder *encoder))block; + +/** + * Returns a NSString instance with multipart/form-data appended to the boundary. + */ ++ (NSString *)contentTypeHTTPHeaderValueWithBoundary:(NSString *)boundary; +/** + * Convenience class method that returns an instance of this class + */ ++ (instancetype)encoderWithStream:(NSOutputStream *)stream andBoundary:(NSString *)boundary; +/** + * Returns a unique boundary string. + */ ++ (NSString *)generateBoundary; +/** + * Designated initializer + * @param stream NSOutputStream associated with the Multipart request + * @param boundary the unique Boundary string to be used + */ +- (instancetype)initWithStream:(NSOutputStream *)stream + andBoundary:(NSString *)boundary NS_DESIGNATED_INITIALIZER; +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; +/** + * Encodes this block within the boundary on the output stream + */ +- (void)encode:(void (^)(void))block; +/** + * Adds the contents of the file data with given Mime type anf fileName within the boundary in + * stream + */ +- (void)addFileData:(NSData *)data + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name; +/** + * Convenience method for the method above. Converts fileURL to data and calls the above method. + */ +- (void)addFile:(NSURL *)fileURL + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name; +/** + * Adds this field and value in the stream + */ +- (void)addValue:(id)value fieldName:(NSString *)name; +/** + * String referring to the multipart MIME type with boundary + */ +@property(nonatomic, copy, readonly) NSString *contentTypeHTTPHeaderValue; +/** + * Length of the data written to stream + */ +@property(nonatomic, copy, readonly) NSString *contentLengthHTTPHeaderValue; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.m new file mode 100644 index 00000000..927087da --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.m @@ -0,0 +1,208 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSMultipartMimeStreamEncoder.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" +#import "Crashlytics/Shared/FIRCLSByteUtility.h" +#import "Crashlytics/Shared/FIRCLSUUID.h" + +@interface FIRCLSMultipartMimeStreamEncoder () <NSStreamDelegate> + +@property(nonatomic) NSUInteger length; +@property(nonatomic, copy) NSString *boundary; +@property(nonatomic, copy, readonly) NSData *headerData; +@property(nonatomic, copy, readonly) NSData *footerData; +@property(nonatomic, strong) NSOutputStream *outputStream; + +@end + +@implementation FIRCLSMultipartMimeStreamEncoder + ++ (void)populateRequest:(NSMutableURLRequest *)request + withDataFromEncoder:(void (^)(FIRCLSMultipartMimeStreamEncoder *encoder))block { + NSString *boundary = [self generateBoundary]; + + NSOutputStream *stream = [NSOutputStream outputStreamToMemory]; + + FIRCLSMultipartMimeStreamEncoder *encoder = + [[FIRCLSMultipartMimeStreamEncoder alloc] initWithStream:stream andBoundary:boundary]; + + [encoder encode:^{ + block(encoder); + }]; + + [request setValue:encoder.contentTypeHTTPHeaderValue forHTTPHeaderField:@"Content-Type"]; + [request setValue:encoder.contentLengthHTTPHeaderValue forHTTPHeaderField:@"Content-Length"]; + + NSData *data = [stream propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; + request.HTTPBody = data; +} + ++ (NSString *)contentTypeHTTPHeaderValueWithBoundary:(NSString *)boundary { + return [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; +} + ++ (instancetype)encoderWithStream:(NSOutputStream *)stream andBoundary:(NSString *)boundary { + return [[self alloc] initWithStream:stream andBoundary:boundary]; +} + ++ (NSString *)generateBoundary { + return FIRCLSGenerateUUID(); +} + +- (instancetype)initWithStream:(NSOutputStream *)stream andBoundary:(NSString *)boundary { + self = [super init]; + if (!self) { + return nil; + } + + self.outputStream = stream; + + if (!boundary) { + boundary = [FIRCLSMultipartMimeStreamEncoder generateBoundary]; + } + + _boundary = boundary; + + return self; +} + +- (void)encode:(void (^)(void))block { + [self beginEncoding]; + + block(); + + [self endEncoding]; +} + +- (NSString *)contentTypeHTTPHeaderValue { + return [[self class] contentTypeHTTPHeaderValueWithBoundary:self.boundary]; +} + +- (NSString *)contentLengthHTTPHeaderValue { + return [NSString stringWithFormat:@"%lu", (unsigned long)_length]; +} + +#pragma - mark MIME part API +- (void)beginEncoding { + _length = 0; + + [self.outputStream open]; + + [self writeData:self.headerData]; +} + +- (void)endEncoding { + [self writeData:self.footerData]; + + [self.outputStream close]; +} + +- (NSData *)headerData { + return [@"MIME-Version: 1.0\r\n" dataUsingEncoding:NSUTF8StringEncoding]; +} + +- (NSData *)footerData { + return [[NSString stringWithFormat:@"--%@--\r\n", self.boundary] + dataUsingEncoding:NSUTF8StringEncoding]; +} + +- (void)addFileData:(NSData *)data + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name { + if ([data length] == 0) { + FIRCLSErrorLog(@"Unable to MIME encode data with zero length (%@)", name); + return; + } + + if ([name length] == 0 || [fileName length] == 0) { + FIRCLSErrorLog(@"name (%@) or fieldname (%@) is invalid", name, fileName); + return; + } + + NSMutableString *string; + + string = [NSMutableString + stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", + self.boundary, name, fileName]; + + if (mimeType) { + [string appendFormat:@"Content-Type: %@\r\n", mimeType]; + [string appendString:@"Content-Transfer-Encoding: binary\r\n\r\n"]; + } else { + [string appendString:@"Content-Type: application/octet-stream\r\n\r\n"]; + } + + [self writeData:[string dataUsingEncoding:NSUTF8StringEncoding]]; + + [self writeData:data]; + + [self writeData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; +} + +- (void)addValue:(id)value fieldName:(NSString *)name { + if ([name length] == 0 || !value || value == NSNull.null) { + FIRCLSErrorLog(@"name (%@) or value (%@) is invalid", name, value); + return; + } + + NSMutableString *string; + + string = + [NSMutableString stringWithFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n", + self.boundary, name]; + [string appendString:@"Content-Type: text/plain\r\n\r\n"]; + [string appendFormat:@"%@\r\n", value]; + + [self writeData:[string dataUsingEncoding:NSUTF8StringEncoding]]; +} + +- (void)addFile:(NSURL *)fileURL + fileName:(NSString *)fileName + mimeType:(NSString *)mimeType + fieldName:(NSString *)name { + NSData *data = [NSData dataWithContentsOfURL:fileURL]; + + [self addFileData:data fileName:fileName mimeType:mimeType fieldName:name]; +} + +- (BOOL)writeBytes:(const void *)bytes ofLength:(NSUInteger)length { + if ([self.outputStream write:bytes maxLength:length] != length) { + FIRCLSErrorLog(@"Failed to write bytes to stream"); + return NO; + } + + _length += length; + + return YES; +} + +- (void)writeData:(NSData *)data { + FIRCLSEnumerateByteRangesOfNSDataUsingBlock( + data, ^(const void *bytes, NSRange byteRange, BOOL *stop) { + NSUInteger length = byteRange.length; + + if ([self.outputStream write:bytes maxLength:length] != length) { + FIRCLSErrorLog(@"Failed to write data to stream"); + *stop = YES; + return; + } + + self->_length += length; + }); +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h new file mode 100644 index 00000000..42f0bb49 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h @@ -0,0 +1,87 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +/** + * Type to indicate response status + */ +typedef NS_ENUM(NSInteger, FIRCLSNetworkClientResponseType) { + FIRCLSNetworkClientResponseSuccess, + FIRCLSNetworkClientResponseInvalid, + FIRCLSNetworkClientResponseFailure, + FIRCLSNetworkClientResponseRetry, + FIRCLSNetworkClientResponseBackOff +}; + +typedef NS_ENUM(NSInteger, FIRCLSNetworkErrorType) { + FIRCLSNetworkErrorUnknown = -1, + FIRCLSNetworkErrorFailedToStartOperation = -3, + FIRCLSNetworkErrorResponseInvalid = -4, + FIRCLSNetworkErrorRequestFailed = -5, + FIRCLSNetworkErrorMaximumAttemptsReached = -6, +}; + +extern NSInteger const FIRCLSNetworkErrorUnknownURLCancelReason; + +/** + * This block is an input parameter to handleCompletedResponse: and handleCompletedTask: methods of + * this class. + * @param retryMightSucceed is YES if the request should be retried. + * @param error is the error received back in response. + */ +typedef void (^FIRCLSNetworkResponseCompletionHandlerBlock)(BOOL retryMightSucceed, NSError *error); + +/** + * Error domain for Crashlytics network errors + */ +extern NSString *const FIRCLSNetworkErrorDomain; +/** + * This class handles network responses. + */ +@interface FIRCLSNetworkResponseHandler : NSObject +/** + * Returns the header in the given NSURLResponse with name as key + */ ++ (NSString *)headerForResponse:(NSURLResponse *)response withKey:(NSString *)key; +/** + * Returns Retry-After header value in response, and if absent returns a default retry value + */ ++ (NSTimeInterval)retryValueForResponse:(NSURLResponse *)response; +/** + * Checks if the content type for response matches the request + */ ++ (BOOL)contentTypeForResponse:(NSURLResponse *)response matchesRequest:(NSURLRequest *)request; + ++ (NSInteger)cancelReasonFromURLError:(NSError *)error; + ++ (BOOL)retryableURLError:(NSError *)error; + +/** + * Convenience method that calls back the input block with FIRCLSNetworkClientResponseType after + * checking the response code in response + */ ++ (void)clientResponseType:(NSURLResponse *)response + handler:(void (^)(FIRCLSNetworkClientResponseType type, + NSInteger statusCode))responseTypeAndStatusCodeHandlerBlock; +/** + * Handles a completed response for request and calls back input block. Populates error even if + * error was nil, but response code indicated an error. + */ ++ (void)handleCompletedResponse:(NSURLResponse *)response + forOriginalRequest:(NSURLRequest *)originalRequest + error:(NSError *)error + block:(FIRCLSNetworkResponseCompletionHandlerBlock)completionHandlerBlock; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.m new file mode 100644 index 00000000..c46f6ec7 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.m @@ -0,0 +1,290 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSNetworkResponseHandler.h" + +@implementation FIRCLSNetworkResponseHandler + +static const NSTimeInterval kFIRCLSNetworkResponseHandlerDefaultRetryInterval = 2.0; +static NSString *const kFIRCLSNetworkResponseHandlerContentType = @"Content-Type"; +NSString *const FIRCLSNetworkErrorDomain = @"FIRCLSNetworkError"; + +NSInteger const FIRCLSNetworkErrorUnknownURLCancelReason = -1; + +#pragma mark - Header Handling ++ (NSString *)headerForResponse:(NSURLResponse *)response withKey:(NSString *)key { + if (![response respondsToSelector:@selector(allHeaderFields)]) { + return nil; + } + + return [((NSHTTPURLResponse *)response).allHeaderFields objectForKey:key]; +} + ++ (NSTimeInterval)retryValueForResponse:(NSURLResponse *)response { + NSString *retryValueString = [self headerForResponse:response withKey:@"Retry-After"]; + if (!retryValueString) { + return kFIRCLSNetworkResponseHandlerDefaultRetryInterval; + } + + NSTimeInterval value = retryValueString.doubleValue; + if (value < 0.0) { + return kFIRCLSNetworkResponseHandlerDefaultRetryInterval; + } + + return value; +} + ++ (NSString *)requestIdForResponse:(NSURLResponse *)response { + return [self headerForResponse:response withKey:@"X-Request-Id"]; +} + ++ (BOOL)contentTypeForResponse:(NSURLResponse *)response matchesRequest:(NSURLRequest *)request { + NSString *accept = [request.allHTTPHeaderFields objectForKey:@"Accept"]; + if (!accept) { + // An omitted accept header is defined to match everything + return YES; + } + + NSString *contentHeader = [self.class headerForResponse:response + withKey:kFIRCLSNetworkResponseHandlerContentType]; + if (!contentHeader) { + // FIRCLSDeveloperLog("Network", @"Content-Type not present in response"); + return NO; + } + + NSString *acceptCharset = request.allHTTPHeaderFields[@"Accept-Charset"]; + + NSArray *parts = [contentHeader componentsSeparatedByString:@"; charset="]; + if (!parts) { + parts = @[ contentHeader ]; + } + + if ([[parts objectAtIndex:0] caseInsensitiveCompare:accept] != NSOrderedSame) { + // FIRCLSDeveloperLog("Network", @"Content-Type does not match Accept"); + return NO; + } + + if (!acceptCharset) { + return YES; + } + + if (parts.count < 2) { + return YES; + } + + return [[parts objectAtIndex:1] caseInsensitiveCompare:acceptCharset] == NSOrderedSame; +} + ++ (NSInteger)cancelReasonFromURLError:(NSError *)error { + if (![[error domain] isEqualToString:NSURLErrorDomain]) { + return FIRCLSNetworkErrorUnknownURLCancelReason; + } + + if ([error code] != NSURLErrorCancelled) { + return FIRCLSNetworkErrorUnknownURLCancelReason; + } + + NSNumber *reason = [[error userInfo] objectForKey:NSURLErrorBackgroundTaskCancelledReasonKey]; + if (reason == nil) { + return FIRCLSNetworkErrorUnknownURLCancelReason; + } + + return [reason integerValue]; +} + ++ (BOOL)retryableURLError:(NSError *)error { + // So far, the only task errors seen are NSURLErrorDomain. For others, we're not + // sure what to do. + if (![[error domain] isEqualToString:NSURLErrorDomain]) { + return NO; + } + + // cases that we know are definitely not retryable + switch ([error code]) { + case NSURLErrorBadURL: + case NSURLErrorUnsupportedURL: + case NSURLErrorHTTPTooManyRedirects: + case NSURLErrorRedirectToNonExistentLocation: + case NSURLErrorUserCancelledAuthentication: + case NSURLErrorUserAuthenticationRequired: + case NSURLErrorAppTransportSecurityRequiresSecureConnection: + case NSURLErrorFileDoesNotExist: + case NSURLErrorFileIsDirectory: + case NSURLErrorDataLengthExceedsMaximum: + case NSURLErrorSecureConnectionFailed: + case NSURLErrorServerCertificateHasBadDate: + case NSURLErrorServerCertificateUntrusted: + case NSURLErrorServerCertificateHasUnknownRoot: + case NSURLErrorServerCertificateNotYetValid: + case NSURLErrorClientCertificateRejected: + case NSURLErrorClientCertificateRequired: + case NSURLErrorBackgroundSessionRequiresSharedContainer: + return NO; + } + + // All other errors, as far as I can tell, are things that could clear up + // without action on the part of the client. + + // NSURLErrorCancelled is a potential special-case. I believe there are + // situations where a cancelled request cannot be successfully restarted. But, + // until I can prove it, we'll retry. There are defnitely many cases where + // a cancelled request definitely can be restarted and will work. + + return YES; +} + +#pragma mark - Error Creation ++ (NSError *)errorForCode:(NSInteger)code userInfo:(NSDictionary *)userInfo { + return [NSError errorWithDomain:FIRCLSNetworkErrorDomain code:code userInfo:userInfo]; +} + ++ (NSError *)errorForResponse:(NSURLResponse *)response + ofType:(FIRCLSNetworkClientResponseType)type + status:(NSInteger)status { + if (type == FIRCLSNetworkClientResponseSuccess) { + return nil; + } + + NSString *requestId = [self requestIdForResponse:response]; + NSString *contentType = [self headerForResponse:response + withKey:kFIRCLSNetworkResponseHandlerContentType]; + + // this could be nil, so be careful + requestId = requestId ? requestId : @""; + contentType = contentType ? contentType : @""; + + NSDictionary *userInfo = @{ + @"type" : @(type), + @"status_code" : @(status), + @"request_id" : requestId, + @"content_type" : contentType + }; + + // compute a reasonable error code type + NSInteger errorCode = FIRCLSNetworkErrorUnknown; + switch (type) { + case FIRCLSNetworkClientResponseFailure: + errorCode = FIRCLSNetworkErrorRequestFailed; + break; + case FIRCLSNetworkClientResponseInvalid: + errorCode = FIRCLSNetworkErrorResponseInvalid; + break; + default: + break; + } + + return [self errorForCode:errorCode userInfo:userInfo]; +} + ++ (void)clientResponseType:(NSURLResponse *)response + handler:(void (^)(FIRCLSNetworkClientResponseType type, + NSInteger statusCode))responseTypeAndStatusCodeHandlerBlock { + if (![response respondsToSelector:@selector(statusCode)]) { + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseInvalid, 0); + return; + } + + NSInteger code = ((NSHTTPURLResponse *)response).statusCode; + + switch (code) { + case 200: + case 201: + case 202: + case 204: + case 304: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseSuccess, code); + return; + case 420: + case 429: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseBackOff, code); + return; + case 408: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseRetry, code); + return; + case 400: + case 401: + case 403: + case 404: + case 406: + case 410: + case 411: + case 413: + case 419: + case 422: + case 431: + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseFailure, code); + return; + } + + // check for a 5xx + if (code >= 500 && code <= 599) { + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseRetry, code); + return; + } + + responseTypeAndStatusCodeHandlerBlock(FIRCLSNetworkClientResponseInvalid, code); +} + ++ (void)handleCompletedResponse:(NSURLResponse *)response + forOriginalRequest:(NSURLRequest *)originalRequest + error:(NSError *)originalError + block: + (FIRCLSNetworkResponseCompletionHandlerBlock)completionHandlerBlock { + // if we have an error, we can just continue + if (originalError) { + BOOL retryable = [self retryableURLError:originalError]; + + completionHandlerBlock(retryable, originalError); + return; + } + + [self.class clientResponseType:response + handler:^(FIRCLSNetworkClientResponseType type, NSInteger statusCode) { + NSError *error = nil; + + switch (type) { + case FIRCLSNetworkClientResponseInvalid: + error = [self errorForResponse:response + ofType:type + status:statusCode]; + break; + case FIRCLSNetworkClientResponseBackOff: + case FIRCLSNetworkClientResponseRetry: + error = [self errorForResponse:response + ofType:type + status:statusCode]; + completionHandlerBlock(YES, error); + return; + case FIRCLSNetworkClientResponseFailure: + error = [self errorForResponse:response + ofType:type + status:statusCode]; + break; + case FIRCLSNetworkClientResponseSuccess: + if (![self contentTypeForResponse:response + matchesRequest:originalRequest]) { + error = [self errorForResponse:response + ofType:FIRCLSNetworkClientResponseInvalid + status:statusCode]; + break; + } + + break; + } + + completionHandlerBlock(NO, error); + }]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h new file mode 100644 index 00000000..c8fbaa94 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h @@ -0,0 +1,44 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +/** + * This is a convenience class to ease constructing NSURLs. + */ +@interface FIRCLSURLBuilder : NSObject + +/** + * Convenience method that returns a FIRCLSURLBuilder instance with the input base URL appended to + * it. + */ ++ (instancetype)URLWithBase:(NSString *)base; +/** + * Appends the component to the URL being built by FIRCLSURLBuilder instance + */ +- (void)appendComponent:(NSString *)component; +/** + * Escapes and appends the component to the URL being built by FIRCLSURLBuilder instance + */ +- (void)escapeAndAppendComponent:(NSString *)component; +/** + * Adds a query and value to the URL being built + */ +- (void)appendValue:(id)value forQueryParam:(NSString *)param; +/** + * Returns the built URL + */ +- (NSURL *)URL; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.m new file mode 100644 index 00000000..a027e4f1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.m @@ -0,0 +1,103 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSNetworking/FIRCLSURLBuilder.h" + +#import "Crashlytics/Crashlytics/Helpers/FIRCLSLogger.h" + +@interface FIRCLSURLBuilder () + +@property(nonatomic) NSMutableString *URLString; +@property(nonatomic) NSUInteger queryParams; + +- (NSString *)escapeString:(NSString *)string; + +@end + +@implementation FIRCLSURLBuilder + ++ (instancetype)URLWithBase:(NSString *)base { + FIRCLSURLBuilder *url = [[FIRCLSURLBuilder alloc] init]; + + [url appendComponent:base]; + + return url; +} + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _URLString = [[NSMutableString alloc] init]; + _queryParams = 0; + + return self; +} + +- (NSString *)escapeString:(NSString *)string { +#if TARGET_OS_WATCH + // TODO: Question - Why does watchOS use a different encoding from the other platforms and the + // Android SDK? + return + [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet + URLPathAllowedCharacterSet]]; +#else + return + [string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet + .URLQueryAllowedCharacterSet]; +#endif +} + +- (void)appendComponent:(NSString *)component { + if (component.length == 0) { + FIRCLSErrorLog(@"URLBuilder parameter component must not be empty"); + return; + } + + [self.URLString appendString:component]; +} + +- (void)escapeAndAppendComponent:(NSString *)component { + [self appendComponent:[self escapeString:component]]; +} + +- (void)appendValue:(id)value forQueryParam:(NSString *)param { + if (!value) { + return; + } + + if (self.queryParams == 0) { + [self appendComponent:@"?"]; + } else { + [self appendComponent:@"&"]; + } + + self.queryParams += 1; + + [self appendComponent:param]; + [self appendComponent:@"="]; + if ([value isKindOfClass:NSString.class]) { + [self escapeAndAppendComponent:value]; + } else { + [self escapeAndAppendComponent:[value description]]; + } +} + +- (NSURL *)URL { + return [NSURL URLWithString:self.URLString]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h new file mode 100644 index 00000000..07be3340 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h @@ -0,0 +1,58 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h" + +/** + * If the compound operation is sent a @c -[cancel] message while executing, it will attempt to + * cancel all operations on its internal queue, and will return an error in its @c asyncCompletion + * block with this value as its code. + */ +FOUNDATION_EXPORT const NSUInteger FIRCLSCompoundOperationErrorCodeCancelled; + +/** + * If one or more of the operations on the @c compoundQueue fail, this operation returns an error + * in its @c asyncCompletion block with this code, and an array of @c NSErrors keyed on @c + * FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors in the @c userInfo dictionary. + */ +FOUNDATION_EXPORT const NSUInteger FIRCLSCompoundOperationErrorCodeSuboperationFailed; + +/** + * When all the operations complete, this @c FIRCLSCompoundOperation instance's @c asyncCompletion + * block is called. If any errors were passed by the suboperations' @c asyncCompletion blocks, they + * are put in an array which can be accessed in the @c userInfo dictionary in the error parameter + * for this instance's @c asyncCompletion block. + */ +FOUNDATION_EXPORT NSString *const FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors; + +/** + * An operation that executes a collection of suboperations on an internal private queue. Any + * instance of @c FIRCLSFABAsyncOperation passed into this instance's @c operations property has the + * potential to return an @c NSError in its @c asyncCompletion block. This instance's @c + * asyncCompletion block will put all such errors in an @c NSArray and return an @c NSError whose @c + * userInfo contains that array keyed by @c FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors. + */ +@interface FIRCLSCompoundOperation : FIRCLSFABAsyncOperation + +/** + * An array of @c NSOperations to execute, which can include instances of @c FIRCLSFABAsyncOperation + * or + * @c FIRCLSCompoundOperation. This operation will not be marked as finished until all suboperations + * are marked as finished. + */ +@property(copy, nonatomic) NSArray<NSOperation *> *operations; + +@property(strong, nonatomic, readonly) NSOperationQueue *compoundQueue; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.m new file mode 100644 index 00000000..92bd06b1 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.m @@ -0,0 +1,165 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h" + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h" + +#define FIRCLS_DISPATCH_QUEUES_AS_OBJECTS OS_OBJECT_USE_OBJC_RETAIN_RELEASE + +const NSUInteger FIRCLSCompoundOperationErrorCodeCancelled = UINT_MAX - 1; +const NSUInteger FIRCLSCompoundOperationErrorCodeSuboperationFailed = UINT_MAX - 2; + +NSString *const FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors = + @"com.google.firebase.crashlytics.FIRCLSCompoundOperation.error.user-info-key.underlying-" + @"errors"; + +static NSString *const FIRCLSCompoundOperationErrorDomain = + @"com.google.firebase.crashlytics.FIRCLSCompoundOperation.error"; +static char *const FIRCLSCompoundOperationCountingQueueLabel = + "com.google.firebase.crashlytics.FIRCLSCompoundOperation.dispatch-queue.counting-queue"; + +@interface FIRCLSCompoundOperation () + +@property(strong, nonatomic, readwrite) NSOperationQueue *compoundQueue; +@property(assign, nonatomic) NSUInteger completedOperations; +@property(strong, nonatomic) NSMutableArray *errors; +#if FIRCLS_DISPATCH_QUEUES_AS_OBJECTS +@property(strong, nonatomic) dispatch_queue_t countingQueue; +#else +@property(assign, nonatomic) dispatch_queue_t countingQueue; +#endif + +@end + +@implementation FIRCLSCompoundOperation + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _compoundQueue = [[NSOperationQueue alloc] init]; + _completedOperations = 0; + _errors = [NSMutableArray array]; + _countingQueue = + dispatch_queue_create(FIRCLSCompoundOperationCountingQueueLabel, DISPATCH_QUEUE_SERIAL); + + return self; +} + +#if !FIRCLS_DISPATCH_QUEUES_AS_OBJECTS +- (void)dealloc { + if (_countingQueue) { + dispatch_release(_countingQueue); + } +} +#endif + +- (void)main { + for (FIRCLSFABAsyncOperation *operation in self.operations) { + [self injectCompoundAsyncCompletionInOperation:operation]; + [self injectCompoundSyncCompletionInOperation:operation]; + + [self.compoundQueue addOperation:operation]; + } +} + +- (void)cancel { + if (self.compoundQueue.operations.count > 0) { + [self.compoundQueue cancelAllOperations]; + dispatch_sync(self.countingQueue, ^{ + [self attemptCompoundCompletion]; + }); + } else { + for (NSOperation *operation in self.operations) { + [operation cancel]; + } + + // we have to add the operations to the queue in order for their isFinished property to be set + // to true. + [self.compoundQueue addOperations:self.operations waitUntilFinished:NO]; + } + [super cancel]; +} + +- (void)injectCompoundAsyncCompletionInOperation:(FIRCLSFABAsyncOperation *)operation { + __weak FIRCLSCompoundOperation *weakSelf = self; + FIRCLSFABAsyncOperationCompletionBlock originalAsyncCompletion = [operation.asyncCompletion copy]; + FIRCLSFABAsyncOperationCompletionBlock completion = ^(NSError *error) { + __strong FIRCLSCompoundOperation *strongSelf = weakSelf; + + if (originalAsyncCompletion) { + dispatch_sync(strongSelf.countingQueue, ^{ + originalAsyncCompletion(error); + }); + } + + [strongSelf updateCompletionCountsWithError:error]; + }; + operation.asyncCompletion = completion; +} + +- (void)injectCompoundSyncCompletionInOperation:(FIRCLSFABAsyncOperation *)operation { + __weak FIRCLSCompoundOperation *weakSelf = self; + void (^originalSyncCompletion)(void) = [operation.completionBlock copy]; + void (^completion)(void) = ^{ + __strong FIRCLSCompoundOperation *strongSelf = weakSelf; + + if (originalSyncCompletion) { + dispatch_sync(strongSelf.countingQueue, ^{ + originalSyncCompletion(); + }); + } + + dispatch_sync(strongSelf.countingQueue, ^{ + [strongSelf attemptCompoundCompletion]; + }); + }; + operation.completionBlock = completion; +} + +- (void)updateCompletionCountsWithError:(NSError *)error { + dispatch_sync(self.countingQueue, ^{ + if (!error) { + self.completedOperations += 1; + } else { + [self.errors addObject:error]; + } + }); +} + +- (void)attemptCompoundCompletion { + if (self.isCancelled) { + [self finishWithError:[NSError errorWithDomain:FIRCLSCompoundOperationErrorDomain + code:FIRCLSCompoundOperationErrorCodeCancelled + userInfo:@{ + NSLocalizedDescriptionKey : [NSString + stringWithFormat:@"%@ cancelled", self.name] + }]]; + self.asyncCompletion = nil; + } else if (self.completedOperations + self.errors.count == self.operations.count) { + NSError *error = nil; + if (self.errors.count > 0) { + error = [NSError + errorWithDomain:FIRCLSCompoundOperationErrorDomain + code:FIRCLSCompoundOperationErrorCodeSuboperationFailed + userInfo:@{FIRCLSCompoundOperationErrorUserInfoKeyUnderlyingErrors : self.errors}]; + } + [self finishWithError:error]; + } +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h new file mode 100644 index 00000000..e5d2c7ef --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +/** + * Completion block that can be called in your subclass implementation. It is up to you when you + * want to call it. + */ +typedef void (^FIRCLSFABAsyncOperationCompletionBlock)(NSError *__nullable error); + +/** + * FIRCLSFABAsyncOperation is a subclass of NSOperation that allows for asynchronous work to be + * performed, for things like networking, IPC or UI-driven logic. Create your own subclasses to + * encapsulate custom logic. + * @warning When subclassing to create your own operations, be sure to call -[finishWithError:] at + * some point, or program execution will hang. + * @see -[finishWithError:] in FIRCLSFABAsyncOperation_Private.h + */ +@interface FIRCLSFABAsyncOperation : NSOperation + +/** + * Add a callback method for consumers of your subclasses to set when the asynchronous work is + * marked as complete with -[finishWithError:]. + */ +@property(copy, nonatomic, nullable) FIRCLSFABAsyncOperationCompletionBlock asyncCompletion; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.m new file mode 100644 index 00000000..01365e59 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.m @@ -0,0 +1,146 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h" + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h" + +@interface FIRCLSFABAsyncOperation () { + BOOL _internalExecuting; + BOOL _internalFinished; +} + +@property(nonatomic, strong) NSRecursiveLock *lock; + +@end + +@implementation FIRCLSFABAsyncOperation + +- (instancetype)init { + self = [super init]; + if (!self) { + return nil; + } + + _internalExecuting = NO; + _internalFinished = NO; + + _lock = [[NSRecursiveLock alloc] init]; + _lock.name = [NSString stringWithFormat:@"com.google.firebase.crashlytics.%@-lock", [self class]]; + ; + + return self; +} + +#pragma mark - NSOperation Overrides +- (BOOL)isConcurrent { + return YES; +} + +- (BOOL)isAsynchronous { + return YES; +} + +- (BOOL)isExecuting { + [self.lock lock]; + BOOL result = _internalExecuting; + [self.lock unlock]; + + return result; +} + +- (BOOL)isFinished { + [self.lock lock]; + BOOL result = _internalFinished; + [self.lock unlock]; + + return result; +} + +- (void)start { + if ([self checkForCancellation]) { + return; + } + + [self markStarted]; + + [self main]; +} + +#pragma mark - Utilities +- (void)changeValueForKey:(NSString *)key inBlock:(void (^)(void))block { + [self willChangeValueForKey:key]; + block(); + [self didChangeValueForKey:key]; +} + +- (void)lock:(void (^)(void))block { + [self.lock lock]; + block(); + [self.lock unlock]; +} + +- (BOOL)checkForCancellation { + if ([self isCancelled]) { + [self markDone]; + return YES; + } + + return NO; +} + +#pragma mark - State Management +- (void)unlockedMarkFinished { + [self changeValueForKey:@"isFinished" + inBlock:^{ + self->_internalFinished = YES; + }]; +} + +- (void)unlockedMarkStarted { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = YES; + }]; +} + +- (void)unlockedMarkComplete { + [self changeValueForKey:@"isExecuting" + inBlock:^{ + self->_internalExecuting = NO; + }]; +} + +- (void)markStarted { + [self lock:^{ + [self unlockedMarkStarted]; + }]; +} + +- (void)markDone { + [self lock:^{ + [self unlockedMarkComplete]; + [self unlockedMarkFinished]; + }]; +} + +#pragma mark - Protected +- (void)finishWithError:(NSError *)error { + if (self.asyncCompletion) { + self.asyncCompletion(error); + } + [self markDone]; +} + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h new file mode 100644 index 00000000..f2fa4aaf --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h @@ -0,0 +1,32 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h" + +@interface FIRCLSFABAsyncOperation (Private) + +/** + * Subclasses must call this method when they are done performing work. When it is called is up to + * you; it can be directly after kicking of a network request, say, or in the callback for its + * response. Once this method is called, the operation queue it is on will begin executing the next + * waiting operation. If you directly invoked -[start] on the instance, execution will proceed to + * the next code statement. + * @note as soon as this method is called, @c NSOperation's standard @c completionBlock will be + * executed if one exists, as a result of setting the operation's isFinished property to YES, and + * the asyncCompletion block is called. + * @param error Any error to pass to asyncCompletion, or nil if there is none. + */ +- (void)finishWithError:(NSError *__nullable)error; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h new file mode 100644 index 00000000..d70dd661 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSOperation/FIRCLSOperation.h @@ -0,0 +1,19 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSCompoundOperation.h" +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation.h" +#import "Crashlytics/Shared/FIRCLSOperation/FIRCLSFABAsyncOperation_Private.h" diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h new file mode 100644 index 00000000..35b383b0 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.h @@ -0,0 +1,27 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> +#import "Crashlytics/Shared/FIRCLSConstants.h" + +/** + * Generates and returns a UUID + * This is also used by used by Answers to generate UUIDs. + */ +NSString *FIRCLSGenerateUUID(void); + +/** + * Converts the input uint8_t UUID to NSString + */ +NSString *FIRCLSUUIDToNSString(const uint8_t *uuid); diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.m b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.m new file mode 100644 index 00000000..47ce7718 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/Shared/FIRCLSUUID.m @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// 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. + +#import "Crashlytics/Shared/FIRCLSUUID.h" + +#import "Crashlytics/Shared/FIRCLSByteUtility.h" + +static NSInteger const FIRCLSUUIDStringLength = 33; + +#pragma mark Public methods + +NSString *FIRCLSGenerateUUID(void) { + NSString *string; + + CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault); + string = CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, uuid)); + CFRelease(uuid); + + return string; +} + +NSString *FIRCLSUUIDToNSString(const uint8_t *uuid) { + char uuidString[FIRCLSUUIDStringLength]; + + FIRCLSSafeHexToString(uuid, 16, uuidString); + + return [NSString stringWithUTF8String:uuidString]; +} diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h new file mode 100644 index 00000000..9c81868a --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Crashlytics/third_party/libunwind/dwarf.h @@ -0,0 +1,256 @@ +/* libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang <davidm@hpl.hp.com> + +This file is part of libunwind. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#pragma once + +// +#define DWARF_EXTENDED_LENGTH_FLAG (0xffffffff) +#define DWARF_CIE_ID_CIE_FLAG (0) + +// Exception Handling Pointer Encoding constants +#define DW_EH_PE_VALUE_MASK (0x0F) +#define DW_EH_PE_RELATIVE_OFFSET_MASK (0x70) + +// Register Definitions +#define DW_EN_MAX_REGISTER_NUMBER (120) + +enum { + DW_EH_PE_ptr = 0x00, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_signed = 0x08, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + + DW_EH_PE_absptr = 0x00, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80, + DW_EH_PE_omit = 0xFF +}; + +// Unwind Instructions + +#define DW_CFA_OPCODE_MASK (0xC0) +#define DW_CFA_OPERAND_MASK (0x3F) + +enum { + DW_CFA_nop = 0x0, + DW_CFA_set_loc = 0x1, + DW_CFA_advance_loc1 = 0x2, + DW_CFA_advance_loc2 = 0x3, + DW_CFA_advance_loc4 = 0x4, + DW_CFA_offset_extended = 0x5, + DW_CFA_restore_extended = 0x6, + DW_CFA_undefined = 0x7, + DW_CFA_same_value = 0x8, + DW_CFA_register = 0x9, + DW_CFA_remember_state = 0xA, + DW_CFA_restore_state = 0xB, + DW_CFA_def_cfa = 0xC, + DW_CFA_def_cfa_register = 0xD, + DW_CFA_def_cfa_offset = 0xE, + DW_CFA_def_cfa_expression = 0xF, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + + // opcode is in high 2 bits, operand in is lower 6 bits + DW_CFA_advance_loc = 0x40, // operand is delta + DW_CFA_offset = 0x80, // operand is register + DW_CFA_restore = 0xC0, // operand is register + + // GNU extensions + DW_CFA_GNU_window_save = 0x2D, + DW_CFA_GNU_args_size = 0x2E, + DW_CFA_GNU_negative_offset_extended = 0x2F +}; + +// Expression Instructions +enum { + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0A, + DW_OP_const2s = 0x0B, + DW_OP_const4u = 0x0C, + DW_OP_const4s = 0x0D, + DW_OP_const8u = 0x0E, + DW_OP_const8s = 0x0F, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1A, + DW_OP_div = 0x1B, + DW_OP_minus = 0x1C, + DW_OP_mod = 0x1D, + DW_OP_mul = 0x1E, + DW_OP_neg = 0x1F, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2F, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2A, + DW_OP_gt = 0x2B, + DW_OP_le = 0x2C, + DW_OP_lt = 0x2D, + DW_OP_ne = 0x2E, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit2 = 0x32, + DW_OP_lit3 = 0x33, + DW_OP_lit4 = 0x34, + DW_OP_lit5 = 0x35, + DW_OP_lit6 = 0x36, + DW_OP_lit7 = 0x37, + DW_OP_lit8 = 0x38, + DW_OP_lit9 = 0x39, + DW_OP_lit10 = 0x3A, + DW_OP_lit11 = 0x3B, + DW_OP_lit12 = 0x3C, + DW_OP_lit13 = 0x3D, + DW_OP_lit14 = 0x3E, + DW_OP_lit15 = 0x3F, + DW_OP_lit16 = 0x40, + DW_OP_lit17 = 0x41, + DW_OP_lit18 = 0x42, + DW_OP_lit19 = 0x43, + DW_OP_lit20 = 0x44, + DW_OP_lit21 = 0x45, + DW_OP_lit22 = 0x46, + DW_OP_lit23 = 0x47, + DW_OP_lit24 = 0x48, + DW_OP_lit25 = 0x49, + DW_OP_lit26 = 0x4A, + DW_OP_lit27 = 0x4B, + DW_OP_lit28 = 0x4C, + DW_OP_lit29 = 0x4D, + DW_OP_lit30 = 0x4E, + DW_OP_lit31 = 0x4F, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg2 = 0x52, + DW_OP_reg3 = 0x53, + DW_OP_reg4 = 0x54, + DW_OP_reg5 = 0x55, + DW_OP_reg6 = 0x56, + DW_OP_reg7 = 0x57, + DW_OP_reg8 = 0x58, + DW_OP_reg9 = 0x59, + DW_OP_reg10 = 0x5A, + DW_OP_reg11 = 0x5B, + DW_OP_reg12 = 0x5C, + DW_OP_reg13 = 0x5D, + DW_OP_reg14 = 0x5E, + DW_OP_reg15 = 0x5F, + DW_OP_reg16 = 0x60, + DW_OP_reg17 = 0x61, + DW_OP_reg18 = 0x62, + DW_OP_reg19 = 0x63, + DW_OP_reg20 = 0x64, + DW_OP_reg21 = 0x65, + DW_OP_reg22 = 0x66, + DW_OP_reg23 = 0x67, + DW_OP_reg24 = 0x68, + DW_OP_reg25 = 0x69, + DW_OP_reg26 = 0x6A, + DW_OP_reg27 = 0x6B, + DW_OP_reg28 = 0x6C, + DW_OP_reg29 = 0x6D, + DW_OP_reg30 = 0x6E, + DW_OP_reg31 = 0x6F, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg2 = 0x72, + DW_OP_breg3 = 0x73, + DW_OP_breg4 = 0x74, + DW_OP_breg5 = 0x75, + DW_OP_breg6 = 0x76, + DW_OP_breg7 = 0x77, + DW_OP_breg8 = 0x78, + DW_OP_breg9 = 0x79, + DW_OP_breg10 = 0x7A, + DW_OP_breg11 = 0x7B, + DW_OP_breg12 = 0x7C, + DW_OP_breg13 = 0x7D, + DW_OP_breg14 = 0x7E, + DW_OP_breg15 = 0x7F, + DW_OP_breg16 = 0x80, + DW_OP_breg17 = 0x81, + DW_OP_breg18 = 0x82, + DW_OP_breg19 = 0x83, + DW_OP_breg20 = 0x84, + DW_OP_breg21 = 0x85, + DW_OP_breg22 = 0x86, + DW_OP_breg23 = 0x87, + DW_OP_breg24 = 0x88, + DW_OP_breg25 = 0x89, + DW_OP_breg26 = 0x8A, + DW_OP_breg27 = 0x8B, + DW_OP_breg28 = 0x8C, + DW_OP_breg29 = 0x8D, + DW_OP_breg30 = 0x8E, + DW_OP_breg31 = 0x8F, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_addres = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9A, + DW_OP_lo_user = 0xE0, + DW_OP_APPLE_uninit = 0xF0, + DW_OP_hi_user = 0xFF +}; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h new file mode 100644 index 00000000..9a0c943d --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRAppInternal.h @@ -0,0 +1,173 @@ +/* + * Copyright 2017 Google + * + * 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. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRApp.h" +#else +#import <FirebaseCore/FIRApp.h> +#endif + +// The has_include is a workaround so the old IID needed for the FIS tests can find FIRErrors.h +#if __has_include("FirebaseCore/Sources/Private/FIRErrors.h") +#import "FirebaseCore/Sources/Private/FIRErrors.h" +#else +#import <FirebaseCore/FIRErrors.h> +#endif + +@class FIRComponentContainer; +@protocol FIRLibrary; + +/** + * The internal interface to FIRApp. This is meant for first-party integrators, who need to receive + * FIRApp notifications, log info about the success or failure of their configuration, and access + * other internal functionality of FIRApp. + * + * TODO(b/28296561): Restructure this header. + */ +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FIRConfigType) { + FIRConfigTypeCore = 1, + FIRConfigTypeSDK = 2, +}; + +extern NSString *const kFIRDefaultAppName; +extern NSString *const kFIRAppReadyToConfigureSDKNotification; +extern NSString *const kFIRAppDeleteNotification; +extern NSString *const kFIRAppIsDefaultAppKey; +extern NSString *const kFIRAppNameKey; +extern NSString *const kFIRGoogleAppIDKey; + +/** + * The format string for the User Defaults key used for storing the data collection enabled flag. + * This includes formatting to append the Firebase App's name. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledDefaultsKeyFormat; + +/** + * The plist key used for storing the data collection enabled flag. + */ +extern NSString *const kFIRGlobalAppDataCollectionEnabledPlistKey; + +/** + * A notification fired containing diagnostic information when SDK errors occur. + */ +extern NSString *const kFIRAppDiagnosticsNotification; + +/** @var FIRAuthStateDidChangeInternalNotification + @brief The name of the @c NSNotificationCenter notification which is posted when the auth state + changes (e.g. a new token has been produced, a user logs in or out). The object parameter of + the notification is a dictionary possibly containing the key: + @c FIRAuthStateDidChangeInternalNotificationTokenKey (the new access token.) If it does not + contain this key it indicates a sign-out event took place. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotification; + +/** @var FIRAuthStateDidChangeInternalNotificationTokenKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new access token. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationTokenKey; + +/** @var FIRAuthStateDidChangeInternalNotificationAppKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the FIRApp associated with the auth instance. + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationAppKey; + +/** @var FIRAuthStateDidChangeInternalNotificationUIDKey + @brief A key present in the dictionary object parameter of the + @c FIRAuthStateDidChangeInternalNotification notification. The value associated with this + key will contain the new user's UID (or nil if there is no longer a user signed in). + */ +extern NSString *const FIRAuthStateDidChangeInternalNotificationUIDKey; + +@interface FIRApp () + +/** + * A flag indicating if this is the default app (has the default app name). + */ +@property(nonatomic, readonly) BOOL isDefaultApp; + +/* + * The container of interop SDKs for this app. + */ +@property(nonatomic) FIRComponentContainer *container; + +/** + * Creates an error for failing to configure a subspec service. This method is called by each + * FIRApp notification listener. + */ ++ (NSError *)errorForSubspecConfigurationFailureWithDomain:(NSString *)domain + errorCode:(FIRErrorCode)code + service:(NSString *)service + reason:(NSString *)reason; +/** + * Checks if the default app is configured without trying to configure it. + */ ++ (BOOL)isDefaultAppConfigured; + +/** + * Registers a given third-party library with the given version number to be reported for + * analytics. + * + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerLibrary:(nonnull NSString *)name withVersion:(nonnull NSString *)version; + +/** + * Registers a given internal library with the given version number to be reported for + * analytics. + * + * @param library Optional parameter for component registration. + * @param name Name of the library. + * @param version Version of the library. + */ ++ (void)registerInternalLibrary:(nonnull Class<FIRLibrary>)library + withName:(nonnull NSString *)name + withVersion:(nonnull NSString *)version; + +/** + * A concatenated string representing all the third-party libraries and version numbers. + */ ++ (NSString *)firebaseUserAgent; + +/** + * Used by each SDK to send logs about SDK configuration status to Clearcut. + * + * @note This API is a no-op, please remove calls to it. + */ +- (void)sendLogsWithServiceName:(NSString *)serviceName + version:(NSString *)version + error:(NSError *)error; + +/** + * Can be used by the unit tests in eack SDK to reset FIRApp. This method is thread unsafe. + */ ++ (void)resetApps; + +/** + * Can be used by the unit tests in each SDK to set customized options. + */ +- (instancetype)initInstanceWithName:(NSString *)name options:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h new file mode 100644 index 00000000..cb51ee70 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponent.h @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +@class FIRApp; +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Provides a system to clean up cached instances returned from the component system. +NS_SWIFT_NAME(ComponentLifecycleMaintainer) +@protocol FIRComponentLifecycleMaintainer +/// The associated app will be deleted, clean up any resources as they are about to be deallocated. +- (void)appWillBeDeleted:(FIRApp *)app; +@end + +typedef _Nullable id (^FIRComponentCreationBlock)(FIRComponentContainer *container, + BOOL *isCacheable) + NS_SWIFT_NAME(ComponentCreationBlock); + +@class FIRDependency; + +/// Describes the timing of instantiation. Note: new components should default to lazy unless there +/// is a strong reason to be eager. +typedef NS_ENUM(NSInteger, FIRInstantiationTiming) { + FIRInstantiationTimingLazy, + FIRInstantiationTimingAlwaysEager, + FIRInstantiationTimingEagerInDefaultApp +} NS_SWIFT_NAME(InstantiationTiming); + +/// A component that can be used from other Firebase SDKs. +NS_SWIFT_NAME(Component) +@interface FIRComponent : NSObject + +/// The protocol describing functionality provided from the Component. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// The timing of instantiation. +@property(nonatomic, readonly) FIRInstantiationTiming instantiationTiming; + +/// An array of dependencies for the component. +@property(nonatomic, copy, readonly) NSArray<FIRDependency *> *dependencies; + +/// A block to instantiate an instance of the component with the appropriate dependencies. +@property(nonatomic, copy, readonly) FIRComponentCreationBlock creationBlock; + +// There's an issue with long NS_SWIFT_NAMES that causes compilation to fail, disable clang-format +// for the next two methods. +// clang-format off + +/// Creates a component with no dependencies that will be lazily initialized. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:creationBlock:)); + +/// Creates a component to be registered with the component container. +/// +/// @param protocol - The protocol describing functionality provided by the component. +/// @param instantiationTiming - When the component should be initialized. Use .lazy unless there's +/// a good reason to be instantiated earlier. +/// @param dependencies - Any dependencies the `implementingClass` has, optional or required. +/// @param creationBlock - A block to instantiate the component with a container, and if +/// @return A component that can be registered with the component container. ++ (instancetype)componentWithProtocol:(Protocol *)protocol + instantiationTiming:(FIRInstantiationTiming)instantiationTiming + dependencies:(NSArray<FIRDependency *> *)dependencies + creationBlock:(FIRComponentCreationBlock)creationBlock +NS_SWIFT_NAME(init(_:instantiationTiming:dependencies:creationBlock:)); + +// clang-format on + +/// Unavailable. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h new file mode 100644 index 00000000..db2bafef --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentContainer.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * 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. + */ +#import <Foundation/Foundation.h> + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponentType.h") +#import "FirebaseCore/Sources/Private/FIRComponentType.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#else +#import <FirebaseCore/FIRComponentType.h> +#import <FirebaseCore/FIRLibrary.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/// A type-safe macro to retrieve a component from a container. This should be used to retrieve +/// components instead of using the container directly. +#define FIR_COMPONENT(type, container) \ + [FIRComponentType<id<type>> instanceForProtocol:@protocol(type) inContainer:container] + +@class FIRApp; + +/// A container that holds different components that are registered via the +/// `registerAsComponentRegistrant:` call. These classes should conform to `FIRComponentRegistrant` +/// in order to properly register components for Core. +NS_SWIFT_NAME(FirebaseComponentContainer) +@interface FIRComponentContainer : NSObject + +/// A weak reference to the app that an instance of the container belongs to. +@property(nonatomic, weak, readonly) FIRApp *app; + +/// Unavailable. Use the `container` property on `FIRApp`. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h new file mode 100644 index 00000000..6f2aca7b --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRComponentType.h @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +@class FIRComponentContainer; + +NS_ASSUME_NONNULL_BEGIN + +/// Do not use directly. A placeholder type in order to provide a macro that will warn users of +/// mis-matched protocols. +NS_SWIFT_NAME(ComponentType) +@interface FIRComponentType<__covariant T> : NSObject + +/// Do not use directly. A factory method to retrieve an instance that provides a specific +/// functionality. ++ (T)instanceForProtocol:(Protocol *)protocol inContainer:(FIRComponentContainer *)container; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h new file mode 100644 index 00000000..76c0c05f --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRCoreDiagnosticsConnector.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +@class FIRDiagnosticsData; +@class FIROptions; + +NS_ASSUME_NONNULL_BEGIN + +/** Connects FIRCore with the CoreDiagnostics library. */ +@interface FIRCoreDiagnosticsConnector : NSObject + +/** Logs FirebaseCore related data. + * + * @param options The options object containing data to log. + */ ++ (void)logCoreTelemetryWithOptions:(FIROptions *)options; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h new file mode 100644 index 00000000..46e9b7ea --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRDependency.h @@ -0,0 +1,45 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/// A dependency on a specific protocol's functionality. +NS_SWIFT_NAME(Dependency) +@interface FIRDependency : NSObject + +/// The protocol describing functionality being depended on. +@property(nonatomic, strong, readonly) Protocol *protocol; + +/// A flag to specify if the dependency is required or not. +@property(nonatomic, readonly) BOOL isRequired; + +/// Initializes a dependency that is required. Calls `initWithProtocol:isRequired` with `YES` for +/// the required parameter. +/// Creates a required dependency on the specified protocol's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol; + +/// Creates a dependency on the specified protocol's functionality and specify if it's required for +/// the class's functionality. ++ (instancetype)dependencyWithProtocol:(Protocol *)protocol isRequired:(BOOL)required; + +/// Use `dependencyWithProtocol:isRequired:` instead. +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h new file mode 100644 index 00000000..c90d9eec --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrorCode.h @@ -0,0 +1,39 @@ +/* + * Copyright 2017 Google + * + * 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. + */ + +/** Error codes in Firebase error domain. */ +typedef NS_ENUM(NSInteger, FIRErrorCode) { + /** + * Unknown error. + */ + FIRErrorCodeUnknown = 0, + /** + * Loading data from the GoogleService-Info.plist file failed. This is a fatal error and should + * not be ignored. Further calls to the API will fail and/or possibly cause crashes. + */ + FIRErrorCodeInvalidPlistFile = -100, + + /** + * Validating the Google App ID format failed. + */ + FIRErrorCodeInvalidAppID = -101, + + /** + * Error code for failing to configure a specific service. It's deprecated, but + * still used after copybara. + */ + FIRErrorCodeConfigFailed = -114, +}; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h new file mode 100644 index 00000000..19e47328 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRErrors.h @@ -0,0 +1,24 @@ +/* + * Copyright 2017 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +#include "FIRErrorCode.h" + +extern NSString *const kFirebaseErrorDomain; +extern NSString *const kFirebaseConfigErrorDomain; +extern NSString *const kFirebaseCoreErrorDomain; +extern NSString *const kFirebasePerfErrorDomain; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h new file mode 100644 index 00000000..bfff73e5 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRHeartbeatInfo.h @@ -0,0 +1,39 @@ +// Copyright 2019 Google +// +// 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. + +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +@interface FIRHeartbeatInfo : NSObject + +// Enum representing the different heartbeat codes. +typedef NS_ENUM(NSInteger, FIRHeartbeatInfoCode) { + FIRHeartbeatInfoCodeNone = 0, + FIRHeartbeatInfoCodeSDK = 1, + FIRHeartbeatInfoCodeGlobal = 2, + FIRHeartbeatInfoCodeCombined = 3, +}; + +/** + * Get heartbeat code requred for the sdk. + * @param heartbeatTag String representing the sdk heartbeat tag. + * @return Heartbeat code indicating whether or not an sdk/global heartbeat + * needs to be sent + */ ++ (FIRHeartbeatInfoCode)heartbeatCodeForTag:(NSString *)heartbeatTag; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h new file mode 100644 index 00000000..e7a9e077 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLibrary.h @@ -0,0 +1,50 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#ifndef FIRLibrary_h +#define FIRLibrary_h + +#import <Foundation/Foundation.h> + +// The has_include is a workaround so the old IID needed for the FIS tests can find the headers. +#if __has_include("FirebaseCore/Sources/Private/FIRComponent.h") +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#else +#import <FirebaseCore/FIRComponent.h> +#endif + +@class FIRApp; + +NS_ASSUME_NONNULL_BEGIN + +/// Provide an interface to register a library for userAgent logging and availability to others. +NS_SWIFT_NAME(Library) +@protocol FIRLibrary + +/// Returns one or more FIRComponents that will be registered in +/// FIRApp and participate in dependency resolution and injection. ++ (NSArray<FIRComponent *> *)componentsToRegister; + +@optional +/// Implement this method if the library needs notifications for lifecycle events. This method is +/// called when the developer calls `FirebaseApp.configure()`. ++ (void)configureWithApp:(FIRApp *)app; + +@end + +NS_ASSUME_NONNULL_END + +#endif /* FIRLibrary_h */ diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h new file mode 100644 index 00000000..6fd77844 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIRLogger.h @@ -0,0 +1,156 @@ +/* + * Copyright 2017 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIRLoggerLevel.h" +#else +#import <FirebaseCore/FIRLoggerLevel.h> +#endif + +NS_ASSUME_NONNULL_BEGIN + +/** + * The Firebase services used in Firebase logger. + */ +typedef NSString *const FIRLoggerService; + +extern FIRLoggerService kFIRLoggerABTesting; +extern FIRLoggerService kFIRLoggerAdMob; +extern FIRLoggerService kFIRLoggerAnalytics; +extern FIRLoggerService kFIRLoggerAuth; +extern FIRLoggerService kFIRLoggerCrash; +extern FIRLoggerService kFIRLoggerCore; +extern FIRLoggerService kFIRLoggerMLKit; +extern FIRLoggerService kFIRLoggerPerf; +extern FIRLoggerService kFIRLoggerRemoteConfig; + +/** + * The key used to store the logger's error count. + */ +extern NSString *const kFIRLoggerErrorCountKey; + +/** + * The key used to store the logger's warning count. + */ +extern NSString *const kFIRLoggerWarningCountKey; + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Enables or disables Analytics debug mode. + * If set to YES, the logging level for Analytics will be set to FIRLoggerLevelDebug. + * Enabling the debug mode has no effect if the app is running from App Store. + * (required) analytics debug mode flag. + */ +void FIRSetAnalyticsDebugMode(BOOL analyticsDebugMode); + +/** + * Changes the default logging level of FIRLoggerLevelNotice to a user-specified level. + * The default level cannot be set above FIRLoggerLevelNotice if the app is running from App Store. + * (required) log level (one of the FIRLoggerLevel enum values). + */ +void FIRSetLoggerLevel(FIRLoggerLevel loggerLevel); + +/** + * Checks if the specified logger level is loggable given the current settings. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) whether or not this function is called from the Analytics component. + */ +BOOL FIRIsLoggableLevel(FIRLoggerLevel loggerLevel, BOOL analyticsComponent); + +/** + * Logs a message to the Xcode console and the device log. If running from AppStore, will + * not log any messages with a level higher than FIRLoggerLevelNotice to avoid log spamming. + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ +extern void FIRLogBasic(FIRLoggerLevel level, + FIRLoggerService service, + NSString *messageCode, + NSString *message, +// On 64-bit simulators, va_list is not a pointer, so cannot be marked nullable +// See: http://stackoverflow.com/q/29095469 +#if __LP64__ && TARGET_OS_SIMULATOR || TARGET_OS_OSX + va_list args_ptr +#else + va_list _Nullable args_ptr +#endif +); + +/** + * The following functions accept the following parameters in order: + * (required) service name of type FIRLoggerService. + * (required) message code starting from "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * See go/firebase-log-proposal for details. + * (required) message string which can be a format string. + * (optional) the list of arguments to substitute into the format string. + * Example usage: + * FIRLogError(kFIRLoggerCore, @"I-COR000001", @"Configuration of %@ failed.", app.name); + */ +extern void FIRLogError(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogWarning(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogNotice(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogInfo(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); +extern void FIRLogDebug(FIRLoggerService service, NSString *messageCode, NSString *message, ...) + NS_FORMAT_FUNCTION(3, 4); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +@interface FIRLoggerWrapper : NSObject + +/** + * Objective-C wrapper for FIRLogBasic to allow weak linking to FIRLogger + * (required) log level (one of the FIRLoggerLevel enum values). + * (required) service name of type FIRLoggerService. + * (required) message code starting with "I-" which means iOS, followed by a capitalized + * three-character service identifier and a six digit integer message ID that is unique + * within the service. + * An example of the message code is @"I-COR000001". + * (required) message string which can be a format string. + * (optional) variable arguments list obtained from calling va_start, used when message is a format + * string. + */ + ++ (void)logWithLevel:(FIRLoggerLevel)level + withService:(FIRLoggerService)service + withCode:(NSString *)messageCode + withMessage:(NSString *)message + withArgs:(va_list)args; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h new file mode 100644 index 00000000..acaf4586 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FIROptionsInternal.h @@ -0,0 +1,119 @@ +/* + * Copyright 2017 Google + * + * 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. + */ + +#if SWIFT_PACKAGE +// TODO(paulb777): Investigate if there's a common strategy for both Cocoapods and Swift PM. +#import "FIROptions.h" +#else +#import <FirebaseCore/FIROptions.h> +#endif + +/** + * Keys for the strings in the plist file. + */ +extern NSString *const kFIRAPIKey; +extern NSString *const kFIRTrackingID; +extern NSString *const kFIRGoogleAppID; +extern NSString *const kFIRClientID; +extern NSString *const kFIRGCMSenderID; +extern NSString *const kFIRAndroidClientID; +extern NSString *const kFIRDatabaseURL; +extern NSString *const kFIRStorageBucket; +extern NSString *const kFIRBundleID; +extern NSString *const kFIRProjectID; + +/** + * Keys for the plist file name + */ +extern NSString *const kServiceInfoFileName; + +extern NSString *const kServiceInfoFileType; + +/** + * This header file exposes the initialization of FIROptions to internal use. + */ +@interface FIROptions () + +/** + * resetDefaultOptions and initInternalWithOptionsDictionary: are exposed only for unit tests. + */ ++ (void)resetDefaultOptions; + +/** + * Initializes the options with dictionary. The above strings are the keys of the dictionary. + * This is the designated initializer. + */ +- (instancetype)initInternalWithOptionsDictionary:(NSDictionary *)serviceInfoDictionary; + +/** + * defaultOptions and defaultOptionsDictionary are exposed in order to be used in FIRApp and + * other first party services. + */ ++ (FIROptions *)defaultOptions; + ++ (NSDictionary *)defaultOptionsDictionary; + +/** + * Indicates whether or not Analytics collection was explicitly enabled via a plist flag or at + * runtime. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionExplicitlySet; + +/** + * Whether or not Analytics Collection was enabled. Analytics Collection is enabled unless + * explicitly disabled in GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionEnabled; + +/** + * Whether or not Analytics Collection was completely disabled. If YES, then + * isAnalyticsCollectionEnabled will be NO. + */ +@property(nonatomic, readonly) BOOL isAnalyticsCollectionDeactivated; + +/** + * The version ID of the client library, e.g. @"1100000". + */ +@property(nonatomic, readonly, copy) NSString *libraryVersionID; + +/** + * The flag indicating whether this object was constructed with the values in the default plist + * file. + */ +@property(nonatomic) BOOL usingOptionsFromDefaultPlist; + +/** + * Whether or not Measurement was enabled. Measurement is enabled unless explicitly disabled in + * GoogleService-Info.plist. + */ +@property(nonatomic, readonly) BOOL isMeasurementEnabled; + +/** + * Whether or not Analytics was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isAnalyticsEnabled; + +/** + * Whether or not SignIn was enabled in the developer console. + */ +@property(nonatomic, readonly) BOOL isSignInEnabled; + +/** + * Whether or not editing is locked. This should occur after FIROptions has been set on a FIRApp. + */ +@property(nonatomic, getter=isEditingLocked) BOOL editingLocked; + +@end diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h new file mode 100644 index 00000000..93af6cb8 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseCore/Sources/Private/FirebaseCoreInternal.h @@ -0,0 +1,31 @@ +// Copyright 2020 Google LLC +// +// 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. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import FirebaseCore; +#else +#import <FirebaseCore/FirebaseCore.h> +#endif + +#import "FirebaseCore/Sources/Private/FIRAppInternal.h" +#import "FirebaseCore/Sources/Private/FIRComponent.h" +#import "FirebaseCore/Sources/Private/FIRComponentContainer.h" +#import "FirebaseCore/Sources/Private/FIRDependency.h" +#import "FirebaseCore/Sources/Private/FIRHeartbeatInfo.h" +#import "FirebaseCore/Sources/Private/FIRLibrary.h" +#import "FirebaseCore/Sources/Private/FIRLogger.h" +#import "FirebaseCore/Sources/Private/FIROptionsInternal.h" diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h new file mode 100644 index 00000000..cd40f172 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/FirebaseInstallations/Source/Library/Private/FirebaseInstallationsInternal.h @@ -0,0 +1,23 @@ +// Copyright 2020 Google LLC +// +// 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. + +// An umbrella header, for any other libraries in this repo to access Firebase +// Installations Public headers. Any package manager complexity should be +// handled here. + +#if SWIFT_PACKAGE +@import FirebaseInstallations; +#else +#import <FirebaseInstallations/FirebaseInstallations.h> +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h new file mode 100644 index 00000000..b5f6bc94 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/GoogleDataTransport/GDTCORLibrary/Internal/GoogleDataTransportInternal.h @@ -0,0 +1,22 @@ +// Copyright 2020 Google LLC +// +// 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. + +// An umbrella header, for any other libraries in this repo to access Firebase Public and Private +// headers. Any package manager complexity should be handled here. + +#if SWIFT_PACKAGE +@import GoogleDataTransport; +#else +#import <GoogleDataTransport/GoogleDataTransport.h> +#endif diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h new file mode 100644 index 00000000..6581b536 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInterop.h @@ -0,0 +1,66 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +@protocol FIRAnalyticsInteropListener; + +NS_ASSUME_NONNULL_BEGIN + +/// Block typedef callback parameter to getUserPropertiesWithCallback:. +typedef void (^FIRAInteropUserPropertiesCallback)(NSDictionary<NSString *, id> *userProperties); + +/// Connector for bridging communication between Firebase SDKs and FirebaseAnalytics API. +@protocol FIRAnalyticsInterop + +/// Sets user property when trigger event is logged. This API is only available in the SDK. +- (void)setConditionalUserProperty:(NSDictionary<NSString *, id> *)conditionalUserProperty; + +/// Clears user property if set. +- (void)clearConditionalUserProperty:(NSString *)userPropertyName + forOrigin:(NSString *)origin + clearEventName:(NSString *)clearEventName + clearEventParameters:(NSDictionary<NSString *, NSString *> *)clearEventParameters; + +/// Returns currently set user properties. +- (NSArray<NSDictionary<NSString *, NSString *> *> *)conditionalUserProperties:(NSString *)origin + propertyNamePrefix: + (NSString *)propertyNamePrefix; + +/// Returns the maximum number of user properties. +- (NSInteger)maxUserProperties:(NSString *)origin; + +/// Returns the user properties to a callback function. +- (void)getUserPropertiesWithCallback:(FIRAInteropUserPropertiesCallback)callback; + +/// Logs events. +- (void)logEventWithOrigin:(NSString *)origin + name:(NSString *)name + parameters:(nullable NSDictionary<NSString *, id> *)parameters; + +/// Sets user property. +- (void)setUserPropertyWithOrigin:(NSString *)origin name:(NSString *)name value:(id)value; + +/// Registers an Analytics listener for the given origin. +- (void)registerAnalyticsListener:(id<FIRAnalyticsInteropListener>)listener + withOrigin:(NSString *)origin; + +/// Unregisters an Analytics listener for the given origin. +- (void)unregisterAnalyticsListenerWithOrigin:(NSString *)origin; + +@end + +NS_ASSUME_NONNULL_END diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h new file mode 100644 index 00000000..45cde550 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRAnalyticsInteropListener.h @@ -0,0 +1,24 @@ +/* + * Copyright 2019 Google + * + * 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. + */ + +/// Handles events and messages from Analytics. +@protocol FIRAnalyticsInteropListener <NSObject> + +/// Triggers when an Analytics event happens for the registered origin with +/// `FIRAnalyticsInterop`s `registerAnalyticsListener:withOrigin:`. +- (void)messageTriggered:(NSString *)name parameters:(NSDictionary *)parameters; + +@end
\ No newline at end of file diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h new file mode 100644 index 00000000..efc54ab2 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropEventNames.h @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +/// @file FIRInteropEventNames.h + +#import <Foundation/Foundation.h> + +/// Notification open event name. +static NSString *const kFIRIEventNotificationOpen = @"_no"; + +/// Notification foreground event name. +static NSString *const kFIRIEventNotificationForeground = @"_nf"; + +/// Campaign event name. +static NSString *const kFIRIEventFirebaseCampaign = @"_cmp"; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h new file mode 100644 index 00000000..ae440bec --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/Interop/Analytics/Public/FIRInteropParameterNames.h @@ -0,0 +1,73 @@ +/* + * Copyright 2018 Google + * + * 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. + */ + +#import <Foundation/Foundation.h> + +/// @file FIRInteropParameterNames.h +/// +/// Predefined event parameter names used by Firebase. This file is a subset of the +/// FirebaseAnalytics FIRParameterNames.h public header. +/// +/// The origin of your traffic, such as an Ad network (for example, google) or partner (urban +/// airship). Identify the advertiser, site, publication, etc. that is sending traffic to your +/// property. Highly recommended (NSString). +/// <pre> +/// NSDictionary *params = @{ +/// kFIRParameterSource : @"InMobi", +/// // ... +/// }; +/// </pre> +static NSString *const kFIRIParameterSource NS_SWIFT_NAME(AnalyticsParameterSource) = @"source"; + +/// The advertising or marketing medium, for example: cpc, banner, email, push. Highly recommended +/// (NSString). +/// <pre> +/// NSDictionary *params = @{ +/// kFIRParameterMedium : @"email", +/// // ... +/// }; +/// </pre> +static NSString *const kFIRIParameterMedium NS_SWIFT_NAME(AnalyticsParameterMedium) = @"medium"; + +/// The individual campaign name, slogan, promo code, etc. Some networks have pre-defined macro to +/// capture campaign information, otherwise can be populated by developer. Highly Recommended +/// (NSString). +/// <pre> +/// NSDictionary *params = @{ +/// kFIRParameterCampaign : @"winter_promotion", +/// // ... +/// }; +/// </pre> +static NSString *const kFIRIParameterCampaign NS_SWIFT_NAME(AnalyticsParameterCampaign) = + @"campaign"; + +/// Message identifier. +static NSString *const kFIRIParameterMessageIdentifier = @"_nmid"; + +/// Message name. +static NSString *const kFIRIParameterMessageName = @"_nmn"; + +/// Message send time. +static NSString *const kFIRIParameterMessageTime = @"_nmt"; + +/// Message device time. +static NSString *const kFIRIParameterMessageDeviceTime = @"_ndt"; + +/// Topic message. +static NSString *const kFIRIParameterTopic = @"_nt"; + +/// Stores the message_id of the last notification opened by the app. +static NSString *const kFIRIUserPropertyLastNotification = @"_ln"; diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/README.md b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/README.md new file mode 100644 index 00000000..1d9f0f67 --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/README.md @@ -0,0 +1,298 @@ +[](https://cocoapods.org/pods/Firebase) +[](https://cocoapods.org/pods/Firebase) +[](https://cocoapods.org/pods/Firebase) + +[![Actions Status][gh-abtesting-badge]][gh-actions] +[![Actions Status][gh-auth-badge]][gh-actions] +[![Actions Status][gh-core-badge]][gh-actions] +[![Actions Status][gh-crashlytics-badge]][gh-actions] +[![Actions Status][gh-database-badge]][gh-actions] +[![Actions Status][gh-datatransport-badge]][gh-actions] +[![Actions Status][gh-dynamiclinks-badge]][gh-actions] +[![Actions Status][gh-firebasepod-badge]][gh-actions] +[![Actions Status][gh-firestore-badge]][gh-actions] +[![Actions Status][gh-functions-badge]][gh-actions] +[![Actions Status][gh-inappmessaging-badge]][gh-actions] +[![Actions Status][gh-interop-badge]][gh-actions] +[![Actions Status][gh-messaging-badge]][gh-actions] +[![Actions Status][gh-remoteconfig-badge]][gh-actions] +[![Actions Status][gh-storage-badge]][gh-actions] +[![Actions Status][gh-symbolcollision-badge]][gh-actions] +[![Actions Status][gh-zip-badge]][gh-actions] +[](https://travis-ci.org/firebase/firebase-ios-sdk) + +# Firebase Apple Open Source Development + +This repository contains all Apple platform Firebase SDK source except FirebaseAnalytics, +FirebasePerformance, and FirebaseML. + +The repository also includes GoogleUtilities source. The +[GoogleUtilities](GoogleUtilities/README.md) pod is +a set of utilities used by Firebase and other Google products. + +Firebase is an app development platform with tools to help you build, grow and +monetize your app. More information about Firebase can be found at +[https://firebase.google.com](https://firebase.google.com). + +## Installation + +See the three subsections for details about three different installation methods. +1. [Standard pod install](README.md#standard-pod-install) +1. [Installing from the GitHub repo](README.md#installing-from-github) +1. [Experimental Carthage](README.md#carthage-ios-only) + +### Standard pod install + +Go to +[https://firebase.google.com/docs/ios/setup](https://firebase.google.com/docs/ios/setup). + +### Installing from GitHub + +For releases starting with 5.0.0, the source for each release is also deployed +to CocoaPods master and available via standard +[CocoaPods Podfile syntax](https://guides.cocoapods.org/syntax/podfile.html#pod). + +These instructions can be used to access the Firebase repo at other branches, +tags, or commits. + +#### Background + +See +[the Podfile Syntax Reference](https://guides.cocoapods.org/syntax/podfile.html#pod) +for instructions and options about overriding pod source locations. + +#### Accessing Firebase Source Snapshots + +All of the official releases are tagged in this repo and available via CocoaPods. To access a local +source snapshot or unreleased branch, use Podfile directives like the following: + +To access FirebaseFirestore via a branch: +``` +pod 'FirebaseCore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +pod 'FirebaseFirestore', :git => 'https://github.com/firebase/firebase-ios-sdk.git', :branch => 'master' +``` + +To access FirebaseMessaging via a checked out version of the firebase-ios-sdk repo do: + +``` +pod 'FirebaseCore', :path => '/path/to/firebase-ios-sdk' +pod 'FirebaseMessaging', :path => '/path/to/firebase-ios-sdk' +``` + +### Carthage (iOS only) + +Instructions for the experimental Carthage distribution are at +[Carthage](Carthage.md). + +### Rome + +Instructions for installing binary frameworks via +[Rome](https://github.com/CocoaPods/Rome) are at [Rome](Rome.md). + +### Using Firebase from a Framework or a library + +[Using Firebase from a Framework or a library](docs/firebase_in_libraries.md) + +## Development + +To develop Firebase software in this repository, ensure that you have at least +the following software: + + * Xcode 10.3 (or later) + * CocoaPods 1.7.2 (or later) + * [CocoaPods generate](https://github.com/square/cocoapods-generate) + +For the pod that you want to develop: + +`pod gen Firebase{name here}.podspec --local-sources=./ --auto-open --platforms=ios` + +Note: If the CocoaPods cache is out of date, you may need to run +`pod repo update` before the `pod gen` command. + +Note: Set the `--platforms` option to `macos` or `tvos` to develop/test for +those platforms. Since 10.2, Xcode does not properly handle multi-platform +CocoaPods workspaces. + +Firestore has a self contained Xcode project. See +[Firestore/README.md](Firestore/README.md). + +### Development for Catalyst +* `pod gen {name here}.podspec --local-sources=./ --auto-open --platforms=ios` +* Check the Mac box in the App-iOS Build Settings +* Sign the App in the Settings Signing & Capabilities tab +* Click Pods in the Project Manager +* Add Signing to the iOS host app and unit test targets +* Select the Unit-unit scheme +* Run it to build and test + +### Adding a New Firebase Pod + +See [AddNewPod.md](AddNewPod.md). + +### Managing Headers and Imports + +See [HeadersImports.md](HeadersImports.md). + +### Code Formatting + +To ensure that the code is formatted consistently, run the script +[./scripts/style.sh](https://github.com/firebase/firebase-ios-sdk/blob/master/scripts/style.sh) +before creating a PR. + +Travis will verify that any code changes are done in a style compliant way. Install +`clang-format` and `swiftformat`: + +``` +brew install clang-format +brew install swiftformat +``` + +### Running Unit Tests + +Select a scheme and press Command-u to build a component and run its unit tests. + +#### Viewing Code Coverage (Deprecated) + +First, make sure that [xcov](https://github.com/nakiostudio/xcov) is installed with `gem install xcov`. + +After running the `AllUnitTests_iOS` scheme in Xcode, execute +`xcov --workspace Firebase.xcworkspace --scheme AllUnitTests_iOS --output_directory xcov_output` +at Example/ in the terminal. This will aggregate the coverage, and you can run `open xcov_output/index.html` to see the results. + +### Running Sample Apps +In order to run the sample apps and integration tests, you'll need valid +`GoogleService-Info.plist` files for those samples. The Firebase Xcode project contains dummy plist +files without real values, but can be replaced with real plist files. To get your own +`GoogleService-Info.plist` files: + +1. Go to the [Firebase Console](https://console.firebase.google.com/) +2. Create a new Firebase project, if you don't already have one +3. For each sample app you want to test, create a new Firebase app with the sample app's bundle +identifier (e.g. `com.google.Database-Example`) +4. Download the resulting `GoogleService-Info.plist` and add it to the Xcode project. + +## Specific Component Instructions +See the sections below for any special instructions for those components. + +### Firebase Auth + +If you're doing specific Firebase Auth development, see +[the Auth Sample README](FirebaseAuth/Tests/Sample/README.md) for instructions about +building and running the FirebaseAuth pod along with various samples and tests. + +### Firebase Database + +The Firebase Database Integration tests can be run against a locally running Database Emulator +or against a production instance. + +To run against a local emulator instance, invoke `./scripts/run_database_emulator.sh start` before +running the integration test. + +To run against a production instance, provide a valid GoogleServices-Info.plist and copy it to +`FirebaseDatabase/Tests/Resources/GoogleService-Info.plist`. Your Security Rule must be set to +[public](https://firebase.google.com/docs/database/security/quickstart) while your tests are +running. + +### Firebase Storage + +To run the Storage Integration tests, follow the instructions in +[FIRStorageIntegrationTests.m](FirebaseStorage/Tests/Integration/FIRStorageIntegrationTests.m). + +#### Push Notifications + +Push notifications can only be delivered to specially provisioned App IDs in the developer portal. +In order to actually test receiving push notifications, you will need to: + +1. Change the bundle identifier of the sample app to something you own in your Apple Developer +account, and enable that App ID for push notifications. +2. You'll also need to +[upload your APNs Provider Authentication Key or certificate to the Firebase Console](https://firebase.google.com/docs/cloud-messaging/ios/certs) +at **Project Settings > Cloud Messaging > [Your Firebase App]**. +3. Ensure your iOS device is added to your Apple Developer portal as a test device. + +#### iOS Simulator + +The iOS Simulator cannot register for remote notifications, and will not receive push notifications. +In order to receive push notifications, you'll have to follow the steps above and run the app on a +physical device. + +## Community Supported Efforts + +We've seen an amazing amount of interest and contributions to improve the Firebase SDKs, and we are +very grateful! We'd like to empower as many developers as we can to be able to use Firebase and +participate in the Firebase community. + +### tvOS, macOS, watchOS and Catalyst +Thanks to contributions from the community, many of Firebase SDKs now compile, run unit tests, and work on +tvOS, macOS, watchOS and Catalyst. + +For tvOS, checkout the [Sample](Example/tvOSSample). +For watchOS, currently only Messaging and Storage (and their dependencies) have limited support. Checkout the +[Independent Watch App Sample](Example/watchOSSample). + +Keep in mind that macOS, tvOS, watchOS and Catalyst are not officially supported by Firebase, and this +repository is actively developed primarily for iOS. While we can catch basic unit test issues with +Travis, there may be some changes where the SDK no longer works as expected on macOS, tvOS or watchOS. If you +encounter this, please [file an issue](https://github.com/firebase/firebase-ios-sdk/issues). + +During app setup in the console, you may get to a step that mentions something like "Checking if the app +has communicated with our servers". This relies on Analytics and will not work on macOS/tvOS/watchOS/Catalyst. +**It's safe to ignore the message and continue**, the rest of the SDKs will work as expected. + +To install, add a subset of the following to the Podfile: + +``` +pod 'Firebase/ABTesting' # No watchOS support yet +pod 'Firebase/Auth' # No watchOS support yet +pod 'Firebase/Crashlytics' # No watchOS support yet +pod 'Firebase/Database' # No watchOS support yet +pod 'Firebase/Firestore' # No watchOS support yet +pod 'Firebase/Functions' # No watchOS support yet +pod 'Firebase/Messaging' +pod 'Firebase/RemoteConfig' # No watchOS support yet +pod 'Firebase/Storage' +``` + +#### Additional Catalyst Notes + +* FirebaseAuth and FirebaseMessaging require adding `Keychain Sharing Capability` +to Build Settings. +* FirebaseFirestore requires signing the +[gRPC Resource target](https://github.com/firebase/firebase-ios-sdk/issues/3500#issuecomment-518741681). + +## Roadmap + +See [Roadmap](ROADMAP.md) for more about the Firebase iOS SDK Open Source +plans and directions. + +## Contributing + +See [Contributing](CONTRIBUTING.md) for more information on contributing to the Firebase +iOS SDK. + +## License + +The contents of this repository is licensed under the +[Apache License, version 2.0](http://www.apache.org/licenses/LICENSE-2.0). + +Your use of Firebase is governed by the +[Terms of Service for Firebase Services](https://firebase.google.com/terms/). + +[gh-actions]: https://github.com/firebase/firebase-ios-sdk/actions +[gh-abtesting-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/abtesting/badge.svg +[gh-auth-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/auth/badge.svg +[gh-core-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/core/badge.svg +[gh-crashlytics-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/crashlytics/badge.svg +[gh-database-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/database/badge.svg +[gh-datatransport-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/datatransport/badge.svg +[gh-dynamiclinks-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/dynamiclinks/badge.svg +[gh-firebasepod-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firebasepod/badge.svg +[gh-firestore-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/firestore/badge.svg +[gh-functions-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/functions/badge.svg +[gh-inappmessaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/inappmessaging/badge.svg +[gh-interop-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/interop/badge.svg +[gh-messaging-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/messaging/badge.svg +[gh-remoteconfig-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/remoteconfig/badge.svg +[gh-storage-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/storage/badge.svg +[gh-symbolcollision-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/symbolcollision/badge.svg +[gh-zip-badge]: https://github.com/firebase/firebase-ios-sdk/workflows/zip/badge.svg diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/run b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/run new file mode 100755 index 00000000..9316eeaf --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/run @@ -0,0 +1,76 @@ +#!/bin/sh + +# Copyright 2019 Google +# +# 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. +# +# run +# +# This script is meant to be run as a Run Script in the "Build Phases" section +# of your Xcode project. It sends debug symbols to symbolicate stacktraces, +# sends build events to track versions, and onboards apps for Crashlytics. +# +# This script calls upload-symbols twice: +# +# 1) First it calls upload-symbols synchronously in "validation" mode. If the +# script finds issues with the build environment, it will report errors to Xcode. +# In validation mode it exits before doing any time consuming work. +# +# 2) Then it calls upload-symbols in the background to actually send the build +# event and upload symbols. It does this in the background so that it doesn't +# slow down your builds. If an error happens here, you won't see it in Xcode. +# +# You can find the output for the background execution in Console.app, by +# searching for "upload-symbols". +# +# If you want verbose output, you can pass the --debug flag to this script +# + +# Figure out where we're being called from +DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) + +# If the first argument is specified without a dash, treat it as the Fabric API +# Key and add it as an argument. +if [ -z "$1" ] || [[ $1 == -* ]]; then + API_KEY_ARG="" +else + API_KEY_ARG="-a $1"; shift +fi + +# Build up the arguments list, passing through any flags added after the +# API Key +ARGUMENTS="$API_KEY_ARG $@" +VALIDATE_ARGUMENTS="$ARGUMENTS --build-phase --validate" +UPLOAD_ARGUMENTS="$ARGUMENTS --build-phase" + +# Quote the path to handle folders with special characters +COMMAND_PATH="\"$DIR/upload-symbols\" " + +# Ensure params are as expected, run in sync mode to validate, +# and cause a build error if validation fails +eval $COMMAND_PATH$VALIDATE_ARGUMENTS +return_code=$? + +if [[ $return_code != 0 ]]; then + exit $return_code +fi + +# Verification passed, convert and upload cSYMs in the background to prevent +# build delays +# +# Note: Validation is performed again at this step before upload +# +# Note: Output can still be found in Console.app, by searching for +# "upload-symbols" +# +eval $COMMAND_PATH$UPLOAD_ARGUMENTS > /dev/null 2>&1 & diff --git a/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/upload-symbols b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/upload-symbols Binary files differnew file mode 100755 index 00000000..76738d0c --- /dev/null +++ b/StoneIsland/platforms/ios/Pods/FirebaseCrashlytics/upload-symbols |
