From e961bc494411e94867aa686d74b40f4245f2b403 Mon Sep 17 00:00:00 2001 From: Tommy Muir <31448720+Muirey03@users.noreply.github.com> Date: Wed, 27 May 2020 16:47:11 +0100 Subject: [PATCH] Support for swift error messages --- cr4shedmach/TweakMach.xm | 36 ++++++++++++++++++++++++++++++++- cr4shedmach/cr4shed_mach.h | 2 ++ cr4shedmach/mach_utils.h | 13 ++++++++++++ cr4shedmach/mach_utils.mm | 41 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) diff --git a/cr4shedmach/TweakMach.xm b/cr4shedmach/TweakMach.xm index 0c58492..e2f1ff7 100644 --- a/cr4shedmach/TweakMach.xm +++ b/cr4shedmach/TweakMach.xm @@ -126,7 +126,39 @@ info->thread_num = threadNum; info->thread_name = threadNames.count > threadNum ? threadNames[threadNum] : nil; info->register_info = get_register_info(thread); - + + //get annotation: + NSString* libSwiftPath = nil; + mach_vm_address_t staticAnnotationAddr = findSymbolInTask(task, "_gCRAnnotations", @"libswiftCore.dylib", &libSwiftPath); + NSString* swiftErrorMessage = nil; + if (staticAnnotationAddr && libSwiftPath.length) + { + NSArray* images = CR4GetIvar(self, "_binaryImages"); + mach_vm_address_t annotationAddr = 0; + for (NSDictionary* img in images) + { + if ([img[@"ExecutablePath"] isEqualToString:libSwiftPath]) + { + uint64_t start = [img[@"StartAddress"] unsignedLongLongValue]; + annotationAddr = staticAnnotationAddr + start; + break; + } + } + + if (annotationAddr) + { + mach_vm_address_t msgAddr = 0; + rread(task, annotationAddr + offsetof(crashreporter_annotations_t, message), &msgAddr, sizeof(mach_vm_address_t)); + if (msgAddr) + { + swiftErrorMessage = [self _readStringAtTaskAddress:msgAddr immutableOnly:NO maxLength:0]; + if ([swiftErrorMessage hasSuffix:@"\n"]) + swiftErrorMessage = [swiftErrorMessage substringWithRange:NSMakeRange(0, swiftErrorMessage.length - 1)]; + } + } + } + info->swiftErrorMessage = swiftErrorMessage; + //get unsymbolicated backtrace: __block NSMutableArray* callStackSymbols = nil; __block NSInteger i = 0; @@ -224,6 +256,8 @@ info->exception_subtype, info->exception_codes, culprit]; + if (info->swiftErrorMessage) + [logStr appendFormat:@"Swift Error Message: %@\n", info->swiftErrorMessage]; if (info->vm_info) [logStr appendFormat:@"VM Protection: %s\n", info->vm_info]; if (terminationReason.length) diff --git a/cr4shedmach/cr4shed_mach.h b/cr4shedmach/cr4shed_mach.h index e498c48..6d2855a 100644 --- a/cr4shedmach/cr4shed_mach.h +++ b/cr4shedmach/cr4shed_mach.h @@ -6,6 +6,7 @@ struct exception_info NSString* processName; NSString* bundleID; NSString* exception_type; + NSString* swiftErrorMessage; const char* exception_subtype; const char* vm_info; uint64_t thread_num; @@ -34,4 +35,5 @@ struct exception_info -(void)decodeBacktraceWithBlock:(void(^)(NSInteger, id))arg1; -(NSDictionary*)binaryImageDictionaryForAddress:(uint64_t)addr; -(void)generateCr4shedReport; +-(NSString*)_readStringAtTaskAddress:(mach_vm_address_t)addr immutableOnly:(BOOL)imut maxLength:(NSUInteger)maxLen; @end \ No newline at end of file diff --git a/cr4shedmach/mach_utils.h b/cr4shedmach/mach_utils.h index 15767e8..3ffb7cb 100644 --- a/cr4shedmach/mach_utils.h +++ b/cr4shedmach/mach_utils.h @@ -21,6 +21,18 @@ struct register_info uint64_t value; }; +struct crashreporter_annotations_t +{ + uint64_t version; + char* message; + uint64_t signature_string; + uint64_t backtrace; + char* message2; + uint64_t thread; + uint64_t dialog_mode; + uint64_t abort_cause; +}; + NSString* mach_exception_string(exception_type_t exception, NSString* signalName); const char* mach_code_string(exception_type_t type, mach_exception_data_t codes, mach_msg_type_number_t codeCnt); char* mach_exception_codes_string(mach_exception_data_t codes, mach_msg_type_number_t codeCnt); @@ -33,6 +45,7 @@ void freeThreadArray(thread_act_port_array_t threads, mach_msg_type_number_t thr BOOL createDir(NSString* path); void writeStringToFile(NSString* str, NSString* path); NSString* stringFromTime(time_t time, CR4DateFormat type); +mach_vm_address_t findSymbolInTask(mach_port_t task, const char* symbolName, NSString* lastPathComponent, NSString** imageName); template static inline Type CR4GetIvar(id self, const char* name) { diff --git a/cr4shedmach/mach_utils.mm b/cr4shedmach/mach_utils.mm index a78ed7b..c57369c 100644 --- a/cr4shedmach/mach_utils.mm +++ b/cr4shedmach/mach_utils.mm @@ -2,6 +2,7 @@ @import Foundation; #import "mach_utils.h" +#import "symbolication.h" #include #include #include @@ -297,3 +298,43 @@ void writeStringToFile(NSString* str, NSString* path) } return str; } + +mach_vm_address_t findSymbolInTask(mach_port_t task, const char* symbolName, NSString* lastPathComponent, NSString** imageName) +{ + CSSymbolicatorRef symbolicator = CSSymbolicatorCreateWithTask(task); + if (CSIsNull(symbolicator)) + return 0; + + __block mach_vm_address_t addr = 0; + __block NSString* imagePath = nil; + CSSymbolicatorForeachSymbolAtTime(symbolicator, kCSNow, ^int(CSSymbolRef symbol){ + if (!CSIsNull(symbol)) + { + const char* name = CSSymbolGetMangledName(symbol); + if (name && symbolName) + { + if (strcmp(name, symbolName) == 0) + { + mach_vm_address_t symAddr = CSSymbolGetRange(symbol).location; + CSSymbolOwnerRef owner = CSSymbolGetSymbolOwner(symbol); + if (!CSIsNull(owner)) + { + const char* c_path = CSSymbolOwnerGetPath(owner); + NSString* path = c_path ? @(c_path) : nil; + if ([path.lastPathComponent isEqualToString:lastPathComponent]) + { + addr = symAddr - CSSymbolOwnerGetBaseAddress(owner); + imagePath = path; + return 0; + } + } + } + } + } + return 1; + }); + CSRelease(symbolicator); + if (imageName) + *imageName = imagePath; + return addr; +}