diff --git a/README.md b/README.md index 2ba6a3c2..21d0d51d 100644 --- a/README.md +++ b/README.md @@ -17,26 +17,27 @@ The source code is also available from my Github repository at: Usage ----- - class-dump 3.5 (64 bit) + class-dump 3.5b1 (64 bit) Usage: class-dump [options] where options are: - -a show instance variable offsets - -A show implementation addresses - --arch choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64) - -C only display classes matching regular expression - -f find string in method name - -H generate header files in current directory, or directory specified with -o - -I sort classes, categories, and protocols by inheritance (overrides -s) - -o output directory used for -H - -r recursively expand frameworks and fixed VM shared libraries - -s sort classes and categories by name - -S sort methods by name - -t suppress header in output, for testing - --list-arches list the arches in the file, then exit - --sdk-ios specify iOS SDK version (will look in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk - --sdk-mac specify Mac OS X version (will look in /Developer/SDKs/MacOSX.sdk - --sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut) + -a show instance variable offsets + -A show implementation addresses + --arch choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64) + -C only display classes matching regular expression + -f find string in method name + -H generate header files in current directory, or directory specified with -o + -I sort classes, categories, and protocols by inheritance (overrides -s) + -o output directory used for -H + -r recursively expand frameworks and fixed VM shared libraries + -R / replace matching regular expression by the str + -s sort classes and categories by name + -S sort methods by name + -t suppress header in output, for testing + --list-arches list the arches in the file, then exit + --sdk-ios specify iOS SDK version (will look in /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk + --sdk-mac specify Mac OS X version (will look in /Developer/SDKs/MacOSX.sdk + --sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut) - class-dump AppKit: diff --git a/Source/CDClassDump.h b/Source/CDClassDump.h index 374b928d..8d88234b 100644 --- a/Source/CDClassDump.h +++ b/Source/CDClassDump.h @@ -3,9 +3,11 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191124 BlackDady Add Option Replace (regex format) + #import "CDFile.h" // For CDArch -#define CLASS_DUMP_BASE_VERSION "3.5 (64 bit)" +#define CLASS_DUMP_BASE_VERSION "3.5b1 (64 bit)" #ifdef DEBUG #define CLASS_DUMP_VERSION CLASS_DUMP_BASE_VERSION " (Debug version compiled " __DATE__ " " __TIME__ ")" @@ -30,7 +32,11 @@ @property (assign) BOOL shouldShowMethodAddresses; @property (assign) BOOL shouldShowHeader; + @property (strong) NSRegularExpression *regularExpression; + +@property (strong) NSMutableDictionary *dictReplaceRegularExpressions; // M_20191124 END M_20191124 + - (BOOL)shouldShowName:(NSString *)name; @property (strong) NSString *sdkRoot; @@ -53,6 +59,9 @@ - (void)appendHeaderToString:(NSMutableString *)resultString; +- (void)replacePartsToMutableString:(NSMutableString *)resultString; // M_20191124 END M_20191124 +- (NSString *)replacePartsToString:(NSString *)txtInput; // M_20191124 END M_20191124 + - (void)registerTypes; - (void)showHeader; diff --git a/Source/CDClassDump.m b/Source/CDClassDump.m index 882a9508..30ac17f7 100644 --- a/Source/CDClassDump.m +++ b/Source/CDClassDump.m @@ -3,6 +3,8 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191124 BlackDady Add Option Replace (regex format) + #import "CDClassDump.h" #import "CDFatArch.h" @@ -40,13 +42,18 @@ @implementation CDClassDump BOOL _shouldShowMethodAddresses; BOOL _shouldShowHeader; + NSRegularExpression *_regularExpression; + NSMutableDictionary *_dictReplaceRegularExpressions; // M_20191124 END M_20191124 + NSString *_sdkRoot; NSMutableArray *_machOFiles; NSMutableDictionary *_machOFilesByName; NSMutableArray *_objcProcessors; + + CDTypeController *_typeController; CDArch _targetArch; @@ -62,6 +69,8 @@ - (id)init; _machOFilesByName = [[NSMutableDictionary alloc] init]; _objcProcessors = [[NSMutableArray alloc] init]; + _dictReplaceRegularExpressions = [[NSMutableDictionary alloc] init]; // M_20191124 END M_20191124 + _typeController = [[CDTypeController alloc] initWithClassDump:self]; // These can be ppc, ppc7400, ppc64, i386, x86_64 @@ -79,6 +88,7 @@ - (id)init; - (BOOL)shouldShowName:(NSString *)name; { if (self.regularExpression != nil) { + NSTextCheckingResult *firstMatch = [self.regularExpression firstMatchInString:name options:(NSMatchingOptions)0 range:NSMakeRange(0, [name length])]; return firstMatch != nil; } @@ -265,6 +275,30 @@ - (void)appendHeaderToString:(NSMutableString *)resultString; } } +// M_20191124 +- (void)replacePartsToMutableString:(NSMutableString *)resultString; +{ + NSString *txtOutput = [self replacePartsToString: resultString]; + + [resultString setString:txtOutput]; +} + +- (NSString *)replacePartsToString:(NSString *)txtInput; +{ + NSString __block *txtOutput = txtInput; + + if( (_dictReplaceRegularExpressions != nil) && ([_dictReplaceRegularExpressions count] > 0) ) + { + [_dictReplaceRegularExpressions enumerateKeysAndObjectsUsingBlock:^(NSRegularExpression * _Nonnull regexp, NSString * _Nonnull replaceTemplate, BOOL * _Nonnull stop) { + + txtOutput = [regexp stringByReplacingMatchesInString:txtOutput options:0 range:NSMakeRange(0, [txtOutput length]) withTemplate:replaceTemplate]; + }]; + } + + return txtOutput; +} +// END M_20191124 + - (void)registerTypes; { for (CDObjectiveCProcessor *processor in self.objcProcessors) { diff --git a/Source/CDClassDumpVisitor.m b/Source/CDClassDumpVisitor.m index 200fcbe8..1f0e324e 100644 --- a/Source/CDClassDumpVisitor.m +++ b/Source/CDClassDumpVisitor.m @@ -3,6 +3,8 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191124 BlackDady Add Option Replace (regex format) + #import "CDClassDumpVisitor.h" #include @@ -37,6 +39,8 @@ - (void)willBeginVisiting; - (void)didEndVisiting; { + [self.classDump replacePartsToMutableString:self.resultString]; // M_20191124 END M_20191124 + [super didEndVisiting]; [self writeResultToStandardOutput]; diff --git a/Source/CDFindMethodVisitor.m b/Source/CDFindMethodVisitor.m index 40242912..75cf13ae 100644 --- a/Source/CDFindMethodVisitor.m +++ b/Source/CDFindMethodVisitor.m @@ -3,6 +3,8 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191124 BlackDady Add Option Replace (regex format) + #import "CDFindMethodVisitor.h" #import "CDClassDump.h" @@ -66,6 +68,8 @@ - (void)visitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; - (void)didEndVisiting; { + [self.classDump replacePartsToMutableString:self.resultString]; // M_20191124 END M_20191124 + [self writeResultToStandardOutput]; } diff --git a/Source/CDLCBuildVersion.h b/Source/CDLCBuildVersion.h index 31cfa484..dab78db8 100644 --- a/Source/CDLCBuildVersion.h +++ b/Source/CDLCBuildVersion.h @@ -3,8 +3,26 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191104 BlackDady support Framework Catalina 10.15.1 XCode 11.2b2 + #import "CDLoadCommand.h" +// M_20191104 +#if (!defined(PLATFORM_IOSMAC)) +#define PLATFORM_IOSMAC 6 +#endif + +#if (!defined(PLATFORM_MACCATALYST)) +#define PLATFORM_MACCATALYST 6 +#endif + +#if (!defined(PLATFORM_DRIVERKIT)) +#define PLATFORM_DRIVERKIT 10 +#endif +// END M_20191104 + + + @interface CDLCBuildVersion : CDLoadCommand @property (nonatomic, readonly) NSString *buildVersionString; diff --git a/Source/CDLCBuildVersion.m b/Source/CDLCBuildVersion.m index a635c82d..6010c809 100644 --- a/Source/CDLCBuildVersion.m +++ b/Source/CDLCBuildVersion.m @@ -3,6 +3,8 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191104 BlackDady support Framework Catalina 10.15.1 XCode 11.2b2 + #import "CDLCBuildVersion.h" #import "CDMachOFile.h" @@ -15,10 +17,18 @@ case PLATFORM_TVOS: return @"tvOS"; case PLATFORM_WATCHOS: return @"watchOS"; case PLATFORM_BRIDGEOS: return @"bridgeOS"; - case PLATFORM_IOSMAC: return @"iOS Mac"; + + // M_20191104 + //case PLATFORM_IOSMAC: return @"iOS Mac"; + case PLATFORM_MACCATALYST: return @"macCatalyst"; + // END M_20191104 + case PLATFORM_IOSSIMULATOR: return @"iOS Simulator"; case PLATFORM_TVOSSIMULATOR: return @"tvOS Simulator"; case PLATFORM_WATCHOSSIMULATOR: return @"watchOS Simulator"; + + case PLATFORM_DRIVERKIT: return @"driverKit"; // M_20191104 END M_20191104 + default: return [NSString stringWithFormat:@"Unknown platform %x", platform]; } } diff --git a/Source/CDMultiFileVisitor.m b/Source/CDMultiFileVisitor.m index fc216296..eedebd8c 100644 --- a/Source/CDMultiFileVisitor.m +++ b/Source/CDMultiFileVisitor.m @@ -3,6 +3,8 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191124 BlackDady Add Option Replace (regex format) + #import "CDMultiFileVisitor.h" #import "CDClassDump.h" @@ -115,6 +117,8 @@ - (void)didVisitClass:(CDOCClass *)aClass; NSString *filename = [NSString stringWithFormat:@"%@.h", aClass.name]; if (self.outputPath != nil) filename = [self.outputPath stringByAppendingPathComponent:filename]; + + [self.classDump replacePartsToMutableString:self.resultString]; // M_20191124 END M_20191124 [[self.resultString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filename atomically:YES]; } @@ -154,6 +158,8 @@ - (void)didVisitCategory:(CDOCCategory *)category; if (self.outputPath != nil) filename = [self.outputPath stringByAppendingPathComponent:filename]; + [self.classDump replacePartsToMutableString:self.resultString]; // M_20191124 END M_20191124 + [[self.resultString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filename atomically:YES]; } @@ -184,6 +190,8 @@ - (void)didVisitProtocol:(CDOCProtocol *)protocol; NSString *filename = [NSString stringWithFormat:@"%@-Protocol.h", protocol.name]; if (self.outputPath != nil) filename = [self.outputPath stringByAppendingPathComponent:filename]; + + [self.classDump replacePartsToMutableString:self.resultString]; // M_20191124 END M_20191124 [[self.resultString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filename atomically:YES]; } @@ -383,6 +391,8 @@ - (void)generateStructureHeader; if (self.outputPath != nil) filename = [self.outputPath stringByAppendingPathComponent:filename]; + [self.classDump replacePartsToMutableString:self.resultString]; // M_20191124 END M_20191124 + [[self.resultString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filename atomically:YES]; } diff --git a/class-dump.m b/class-dump.m index 2a1ac2b0..ef7e1f4c 100644 --- a/class-dump.m +++ b/class-dump.m @@ -3,6 +3,9 @@ // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. // Copyright (C) 1997-2019 Steve Nygard. +// M_20191124 BlackDady Add Option Replace (regex format) + + #include #include #include @@ -22,32 +25,36 @@ void print_usage(void) { + + // M_20191124 fprintf(stderr, "class-dump %s\n" "Usage: class-dump [options] \n" "\n" " where options are:\n" - " -a show instance variable offsets\n" - " -A show implementation addresses\n" - " --arch choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64, armv6, armv7, armv7s, arm64)\n" - " -C only display classes matching regular expression\n" - " -f find string in method name\n" - " -H generate header files in current directory, or directory specified with -o\n" - " -I sort classes, categories, and protocols by inheritance (overrides -s)\n" - " -o output directory used for -H\n" - " -r recursively expand frameworks and fixed VM shared libraries\n" - " -s sort classes and categories by name\n" - " -S sort methods by name\n" - " -t suppress header in output, for testing\n" - " --list-arches list the arches in the file, then exit\n" - " --sdk-ios specify iOS SDK version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk\n" - " or /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk)\n" - " --sdk-mac specify Mac OS X version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk\n" - " or /Developer/SDKs/MacOSX.sdk)\n" - " --sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut)\n" + " -a show instance variable offsets\n" + " -A show implementation addresses\n" + " --arch choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64, armv6, armv7, armv7s, arm64)\n" + " -C only display classes matching regular expression\n" + " -f find string in method name\n" + " -H generate header files in current directory, or directory specified with -o\n" + " -I sort classes, categories, and protocols by inheritance (overrides -s)\n" + " -o output directory used for -H\n" + " -r recursively expand frameworks and fixed VM shared libraries\n" + " -R / replace matching regular expression by the str\n" + " -s sort classes and categories by name\n" + " -S sort methods by name\n" + " -t suppress header in output, for testing\n" + " --list-arches list the arches in the file, then exit\n" + " --sdk-ios specify iOS SDK version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk\n" + " or /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk)\n" + " --sdk-mac specify Mac OS X version (will look for /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk\n" + " or /Developer/SDKs/MacOSX.sdk)\n" + " --sdk-root specify the full SDK root path (or use --sdk-ios/--sdk-mac for a shortcut)\n" , CLASS_DUMP_VERSION ); + // END M_20191124 } #define CD_OPT_ARCH 1 @@ -82,6 +89,7 @@ int main(int argc, char *argv[]) { "sort-by-inheritance", no_argument, NULL, 'I' }, { "output-dir", required_argument, NULL, 'o' }, { "recursive", no_argument, NULL, 'r' }, + { "replace", required_argument, NULL, 'R' }, // M_20191124 END M_20191124 { "sort", no_argument, NULL, 's' }, { "sort-methods", no_argument, NULL, 'S' }, { "arch", required_argument, NULL, CD_OPT_ARCH }, @@ -102,7 +110,7 @@ int main(int argc, char *argv[]) CDClassDump *classDump = [[CDClassDump alloc] init]; - while ( (ch = getopt_long(argc, argv, "aAC:f:HIo:rRsSt", longopts, NULL)) != -1) { + while ( (ch = getopt_long(argc, argv, "aAC:f:HIo:rR:sSt", longopts, NULL)) != -1) { // M_20191124 END M_20191124 switch (ch) { case CD_OPT_ARCH: { NSString *name = [NSString stringWithUTF8String:optarg]; @@ -216,6 +224,150 @@ int main(int argc, char *argv[]) classDump.shouldProcessRecursively = YES; break; + // M_20191124 + case 'R': { + NSString *replacePattern = @""; + NSString *replaceTemplate = @""; + + // -R / replace matching regular expression by the str + // There, we transform 1 string in 2 (separated by a / and not escaped) + // + // For : "AppKit/AppKit2" + // - "AppKit" + // - "AppKit2" + // + // For : "a \/ b \\\/ c / d \/ \\\/" + // - "a \/ b \\\/ c " + // - " d \/ \\\/" + // + // For : "a \/ b \\\/ c / d \\/ \\\/" + // - "a \/ b \\\/ c / d \\" + // - " \\\/" + + if( FALSE ) + { + NSError *error; + NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:@"^([^/]+)\\/(.*)$" + options:(NSRegularExpressionOptions)0 + error:&error]; + NSString *allReplacePattern = [NSString stringWithUTF8String:optarg]; + + if (regularExpression != nil) { + + + + replacePattern = [regularExpression stringByReplacingMatchesInString:allReplacePattern + options:0 + range:NSMakeRange(0, [allReplacePattern length]) + withTemplate:@"$1"]; + + replaceTemplate = [regularExpression stringByReplacingMatchesInString:allReplacePattern + options:0 + range:NSMakeRange(0, [allReplacePattern length]) + withTemplate:@"$2"]; + + } + } + else if( FALSE ) + { + // Search last char / but no count it if escaped + if( optarg != nil ) + { + char *ptr = optarg; + char *slash = nil; + BOOL escape = NO; + while( *ptr != 0x00 ) + { + if( escape == YES ) + escape = NO; + else if( *ptr =='\\' ) + escape = YES; + else if( *ptr =='/' ) + slash = ptr; + + ptr++; + } + + if( slash != nil) + { + *slash = 0; + replacePattern = [NSString stringWithUTF8String:optarg]; + replaceTemplate = [NSString stringWithUTF8String:slash+1]; + } + else + replacePattern = [NSString stringWithUTF8String:optarg]; + + } + } + else + { + // Search last char / but no count it if escaped + // Version unicode + + NSString *allReplacePattern = [NSString stringWithUTF8String:optarg]; + + if( allReplacePattern != nil ) + { + NSData * data = [allReplacePattern dataUsingEncoding:NSUnicodeStringEncoding]; + + if( data != nil ) + { + unichar *pdata = (unichar *)data.bytes+1; // +1: ignore 2 bytes bom UTF16: U+FFFE + long ldata = (data.length-2)/sizeof(unichar); // -2: ignore 2 bytes bom UTF16: U+FFFE + unichar *ptr = pdata; + unichar *slash = nil; + BOOL escape = NO; + + + while( ptr < (pdata+data.length) ) + { + if( escape == YES ) + escape = NO; + else if( *ptr == '\\' ) + escape = YES; + else if( *ptr == '/' ) + { + slash = ptr; + + if( TRUE ) // Stop on First slash + break; + } + + ptr++; + } + + if( slash != nil) + { + NSUInteger lenPattern = slash - pdata; + NSUInteger lenTemplate = ldata-lenPattern-1; + + replacePattern = [NSString stringWithCharacters:pdata length: lenPattern]; + replaceTemplate = [NSString stringWithCharacters:slash+1 length: lenTemplate]; + } + else + replacePattern = allReplacePattern; + } + } + } + + NSError *error = nil; + NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:replacePattern + options:NSRegularExpressionCaseInsensitive + error:&error]; + + + if (regularExpression != nil) { + classDump.dictReplaceRegularExpressions[regularExpression] = replaceTemplate; + } else { + fprintf(stderr, "class-dump: Error with regular expression: %s\n\n", [[error localizedFailureReason] UTF8String]); + errorFlag = YES; + } + + // Last one wins now. + break; + } + // END M_20191124 + case 's': classDump.shouldSortClasses = YES; break; diff --git a/class-dump.xcodeproj/project.pbxproj b/class-dump.xcodeproj/project.pbxproj index e448a7f9..a13e7b8f 100644 --- a/class-dump.xcodeproj/project.pbxproj +++ b/class-dump.xcodeproj/project.pbxproj @@ -910,10 +910,11 @@ }; buildConfigurationList = 01EB825913A590D9003EDE60 /* Build configuration list for PBXProject "class-dump" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 01EB825413A590D9003EDE60; productRefGroup = 01EB826013A590D9003EDE60 /* Products */; diff --git a/class-dump.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/class-dump.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/class-dump.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/class-dump.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/class-dump.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 00000000..f9b0d7c5 --- /dev/null +++ b/class-dump.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/class-dump.xcodeproj/xcshareddata/xcschemes/all.xcscheme b/class-dump.xcodeproj/xcshareddata/xcschemes/all.xcscheme new file mode 100644 index 00000000..6dbe913e --- /dev/null +++ b/class-dump.xcodeproj/xcshareddata/xcschemes/all.xcscheme @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/class-dump.xcodeproj/xcshareddata/xcschemes/class-dump.xcscheme b/class-dump.xcodeproj/xcshareddata/xcschemes/class-dump.xcscheme new file mode 100644 index 00000000..fe805c59 --- /dev/null +++ b/class-dump.xcodeproj/xcshareddata/xcschemes/class-dump.xcscheme @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +