├── CDUnitTests-Info.plist ├── CHANGELOG.md ├── Info.plist ├── MachObjC-Prefix.pch ├── README.md ├── Source ├── CDBalanceFormatter.h ├── CDBalanceFormatter.m ├── CDClassDump.h ├── CDClassDump.m ├── CDClassDumpVisitor.h ├── CDClassDumpVisitor.m ├── CDClassFrameworkVisitor.h ├── CDClassFrameworkVisitor.m ├── CDDataCursor.h ├── CDDataCursor.m ├── CDExtensions.h ├── CDFatArch.h ├── CDFatArch.m ├── CDFatFile.h ├── CDFatFile.m ├── CDFile.h ├── CDFile.m ├── CDFindMethodVisitor.h ├── CDFindMethodVisitor.m ├── CDLCBuildVersion.h ├── CDLCBuildVersion.m ├── CDLCDataInCode.h ├── CDLCDataInCode.m ├── CDLCDyldInfo.h ├── CDLCDyldInfo.m ├── CDLCDylib.h ├── CDLCDylib.m ├── CDLCDylinker.h ├── CDLCDylinker.m ├── CDLCDynamicSymbolTable.h ├── CDLCDynamicSymbolTable.m ├── CDLCEncryptionInfo.h ├── CDLCEncryptionInfo.m ├── CDLCFunctionStarts.h ├── CDLCFunctionStarts.m ├── CDLCLinkeditData.h ├── CDLCLinkeditData.m ├── CDLCMain.h ├── CDLCMain.m ├── CDLCPrebindChecksum.h ├── CDLCPrebindChecksum.m ├── CDLCPreboundDylib.h ├── CDLCPreboundDylib.m ├── CDLCRoutines32.h ├── CDLCRoutines32.m ├── CDLCRoutines64.h ├── CDLCRoutines64.m ├── CDLCRunPath.h ├── CDLCRunPath.m ├── CDLCSegment.h ├── CDLCSegment.m ├── CDLCSourceVersion.h ├── CDLCSourceVersion.m ├── CDLCSubClient.h ├── CDLCSubClient.m ├── CDLCSubFramework.h ├── CDLCSubFramework.m ├── CDLCSubLibrary.h ├── CDLCSubLibrary.m ├── CDLCSubUmbrella.h ├── CDLCSubUmbrella.m ├── CDLCSymbolTable.h ├── CDLCSymbolTable.m ├── CDLCTwoLevelHints.h ├── CDLCTwoLevelHints.m ├── CDLCUUID.h ├── CDLCUUID.m ├── CDLCUnixThread.h ├── CDLCUnixThread.m ├── CDLCUnknown.h ├── CDLCUnknown.m ├── CDLCVersionMinimum.h ├── CDLCVersionMinimum.m ├── CDLoadCommand.h ├── CDLoadCommand.m ├── CDMachOFile.h ├── CDMachOFile.m ├── CDMachOFileDataCursor.h ├── CDMachOFileDataCursor.m ├── CDMethodType.h ├── CDMethodType.m ├── CDMultiFileVisitor.h ├── CDMultiFileVisitor.m ├── CDOCCategory.h ├── CDOCCategory.m ├── CDOCClass.h ├── CDOCClass.m ├── CDOCClassReference.h ├── CDOCClassReference.m ├── CDOCInstanceVariable.h ├── CDOCInstanceVariable.m ├── CDOCMethod.h ├── CDOCMethod.m ├── CDOCModule.h ├── CDOCModule.m ├── CDOCProperty.h ├── CDOCProperty.m ├── CDOCProtocol.h ├── CDOCProtocol.m ├── CDOCSymtab.h ├── CDOCSymtab.m ├── CDObjectiveC1Processor.h ├── CDObjectiveC1Processor.m ├── CDObjectiveC2Processor.h ├── CDObjectiveC2Processor.m ├── CDObjectiveCProcessor.h ├── CDObjectiveCProcessor.m ├── CDProtocolUniquer.h ├── CDProtocolUniquer.m ├── CDRelocationInfo.h ├── CDRelocationInfo.m ├── CDSearchPathState.h ├── CDSearchPathState.m ├── CDSection.h ├── CDSection.m ├── CDStructureInfo.h ├── CDStructureInfo.m ├── CDStructureTable.h ├── CDStructureTable.m ├── CDSymbol.h ├── CDSymbol.m ├── CDTextClassDumpVisitor.h ├── CDTextClassDumpVisitor.m ├── CDTopoSortNode.h ├── CDTopoSortNode.m ├── CDTopologicalSortProtocol.h ├── CDType.h ├── CDType.m ├── CDTypeController.h ├── CDTypeController.m ├── CDTypeFormatter.h ├── CDTypeFormatter.m ├── CDTypeLexer.h ├── CDTypeLexer.m ├── CDTypeName.h ├── CDTypeName.m ├── CDTypeParser.h ├── CDTypeParser.m ├── CDVisitor.h ├── CDVisitor.m ├── CDVisitorPropertyState.h ├── CDVisitorPropertyState.m ├── NSArray-CDExtensions.h ├── NSArray-CDExtensions.m ├── NSData-CDExtensions.h ├── NSData-CDExtensions.m ├── NSError-CDExtensions.h ├── NSError-CDExtensions.m ├── NSScanner-CDExtensions.h ├── NSScanner-CDExtensions.m ├── NSString-CDExtensions.h ├── NSString-CDExtensions.m ├── ULEB128.h ├── ULEB128.m └── cd_objc2.h ├── Tests ├── doTests.py └── showdiff ├── ThirdParty ├── blowfish.c └── blowfish.h ├── UnitTests.old ├── AllTests.h ├── AllTests.m ├── CDPathUnitTest.h ├── CDPathUnitTest.m ├── CDStructHandlingUnitTest.h ├── CDStructHandlingUnitTest.m ├── CDTypeFormatterUnitTest.h ├── CDTypeFormatterUnitTest.m ├── CDTypeLexerUnitTest.h ├── CDTypeLexerUnitTest.m ├── CDTypeParserUnitTest.h ├── CDTypeParserUnitTest.m ├── method-001.txt ├── otest-all ├── shud01-in.txt ├── shud01-out.txt ├── shud02-in.txt ├── shud02-out.txt ├── shud04-in.txt ├── shud04-out.txt ├── shud05-in.txt ├── shud05-out.txt ├── shud06-in.txt ├── shud06-out.txt ├── shud07-in.txt ├── shud07-out.txt ├── shud08-in.txt ├── shud08-out.txt ├── shud09-in.txt ├── shud09-out.txt ├── shud10-in.txt ├── shud10-out.txt ├── shud11-in.txt ├── shud11-out.txt ├── shud13-in.txt ├── shud13-out.txt ├── shud14-in.txt ├── shud14-out.txt ├── shud15-in.txt ├── shud15-out.txt ├── shud16-in.txt ├── shud16-out.txt ├── var-001.txt ├── var-002.txt ├── var-003.txt ├── var-004.txt └── var-005.txt ├── UnitTests ├── TestBlockSignature.m ├── TestCDArchFromName.m ├── TestCDArchUses64BitABI.m ├── TestCDNameForCPUType.m ├── TestFatFile_Intel32_64.m ├── TestFatFile_Intel32_64_lib64.m ├── TestFatFile_Intel64_32.m ├── TestFatFile_armv7_v7s.m ├── TestThinFile_Intel64.m ├── TestThinFile_Intel64_lib64.m ├── UnitTests-Info.plist ├── UnitTests-Prefix.pch └── en.lproj │ └── InfoPlist.strings ├── class-dump-Prefix.pch ├── class-dump.m ├── class-dump.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── nygard.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── nygard.xcuserdatad │ └── xcschemes │ ├── MachObjC.xcscheme │ ├── all.xcscheme │ ├── class-dump.xcscheme │ ├── deprotect.xcscheme │ ├── formatType.xcscheme │ └── xcschememanagement.plist ├── deprotect-Prefix.pch ├── deprotect.m ├── formatType-Prefix.pch ├── formatType.m └── keys.txt /CDUnitTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.stevenygard.CDUnitTests 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleSignature 16 | ???? 17 | CFBundleVersion 18 | 1.0 19 | 20 | 21 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | com.stevenygard.class-dump 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | class-dump 13 | 14 | 15 | -------------------------------------------------------------------------------- /MachObjC-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'libMachObjC' target in the 'class-dump' project. 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "CDExtensions.h" 8 | #define __cmd __PRETTY_FUNCTION__ 9 | #endif 10 | -------------------------------------------------------------------------------- /Source/CDBalanceFormatter.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface CDBalanceFormatter : NSObject 7 | 8 | - (id)initWithString:(NSString *)str; 9 | 10 | - (void)parse:(NSString *)open index:(NSUInteger)openIndex level:(NSUInteger)level; 11 | 12 | - (NSString *)format; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Source/CDBalanceFormatter.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDBalanceFormatter.h" 7 | 8 | static BOOL debug = NO; 9 | 10 | @implementation CDBalanceFormatter 11 | { 12 | NSScanner *_scanner; 13 | NSCharacterSet *_openCloseSet; 14 | 15 | NSMutableString *_result; 16 | } 17 | 18 | - (id)initWithString:(NSString *)str; 19 | { 20 | if ((self = [super init])) { 21 | _scanner = [[NSScanner alloc] initWithString:str]; 22 | _openCloseSet = [NSCharacterSet characterSetWithCharactersInString:@"{}<>()"]; 23 | 24 | _result = [[NSMutableString alloc] init]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | #pragma mark - 31 | 32 | - (void)parse:(NSString *)open index:(NSUInteger)openIndex level:(NSUInteger)level; 33 | { 34 | NSString *opens[] = { @"{", @"<", @"(", nil}; 35 | NSString *closes[] = { @"}", @">", @")", nil}; 36 | BOOL foundOpen = NO; 37 | BOOL foundClose = NO; 38 | 39 | while ([_scanner isAtEnd] == NO) { 40 | NSString *pre; 41 | 42 | if ([_scanner scanUpToCharactersFromSet:_openCloseSet intoString:&pre]) { 43 | if (debug) NSLog(@"pre = '%@'", pre); 44 | [_result appendFormat:@"%@%@\n", [NSString spacesIndentedToLevel:level], pre]; 45 | } 46 | if (debug) NSLog(@"remaining: '%@'", [[_scanner string] substringFromIndex:[_scanner scanLocation]]); 47 | 48 | foundOpen = foundClose = NO; 49 | for (NSUInteger index = 0; index < 3; index++) { 50 | if (debug) NSLog(@"Checking open %lu: '%@'", index, opens[index]); 51 | if ([_scanner scanString:opens[index] intoString:NULL]) { 52 | if (debug) NSLog(@"Start %@", opens[index]); 53 | [_result appendSpacesIndentedToLevel:level]; 54 | [_result appendString:opens[index]]; 55 | [_result appendString:@"\n"]; 56 | 57 | [self parse:opens[index] index:[_scanner scanLocation] - 1 level:level + 1]; 58 | 59 | [_result appendSpacesIndentedToLevel:level]; 60 | [_result appendString:closes[index]]; 61 | [_result appendString:@"\n"]; 62 | foundOpen = YES; 63 | break; 64 | } 65 | 66 | if (debug) NSLog(@"Checking close %lu: '%@'", index, closes[index]); 67 | if ([_scanner scanString:closes[index] intoString:NULL]) { 68 | if ([open isEqualToString:opens[index]]) { 69 | if (debug) NSLog(@"End %@", closes[index]); 70 | } else { 71 | NSLog(@"ERROR: Unmatched end %@", closes[index]); 72 | } 73 | foundClose = YES; 74 | break; 75 | } 76 | } 77 | 78 | if (foundOpen == NO && foundClose == NO) { 79 | if (debug) NSLog(@"Unknown @ %lu: %@", [_scanner scanLocation], [[_scanner string] substringFromIndex:[_scanner scanLocation]]); 80 | break; 81 | } 82 | 83 | if (foundClose) 84 | break; 85 | } 86 | } 87 | 88 | - (NSString *)format; 89 | { 90 | [self parse:nil index:0 level:0]; 91 | 92 | if (debug) NSLog(@"result:\n%@", _result); 93 | 94 | return [NSString stringWithString:_result]; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /Source/CDClassDump.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDFile.h" // For CDArch 7 | 8 | #define CLASS_DUMP_BASE_VERSION "3.5 (64 bit)" 9 | 10 | #ifdef DEBUG 11 | #define CLASS_DUMP_VERSION CLASS_DUMP_BASE_VERSION " (Debug version compiled " __DATE__ " " __TIME__ ")" 12 | #else 13 | #define CLASS_DUMP_VERSION CLASS_DUMP_BASE_VERSION 14 | #endif 15 | 16 | @class CDFile; 17 | @class CDTypeController; 18 | @class CDVisitor; 19 | @class CDSearchPathState; 20 | 21 | @interface CDClassDump : NSObject 22 | 23 | @property (readonly) CDSearchPathState *searchPathState; 24 | 25 | @property (assign) BOOL shouldProcessRecursively; 26 | @property (assign) BOOL shouldSortClasses; 27 | @property (assign) BOOL shouldSortClassesByInheritance; 28 | @property (assign) BOOL shouldSortMethods; 29 | @property (assign) BOOL shouldShowIvarOffsets; 30 | @property (assign) BOOL shouldShowMethodAddresses; 31 | @property (assign) BOOL shouldShowHeader; 32 | 33 | @property (strong) NSRegularExpression *regularExpression; 34 | - (BOOL)shouldShowName:(NSString *)name; 35 | 36 | @property (strong) NSString *sdkRoot; 37 | 38 | @property (readonly) NSArray *machOFiles; 39 | @property (readonly) NSArray *objcProcessors; 40 | 41 | @property (assign) CDArch targetArch; 42 | 43 | @property (nonatomic, readonly) BOOL containsObjectiveCData; 44 | @property (nonatomic, readonly) BOOL hasEncryptedFiles; 45 | @property (nonatomic, readonly) BOOL hasObjectiveCRuntimeInfo; 46 | 47 | @property (readonly) CDTypeController *typeController; 48 | 49 | - (BOOL)loadFile:(CDFile *)file error:(NSError **)error; 50 | - (void)processObjectiveCData; 51 | 52 | - (void)recursivelyVisit:(CDVisitor *)visitor; 53 | 54 | - (void)appendHeaderToString:(NSMutableString *)resultString; 55 | 56 | - (void)registerTypes; 57 | 58 | - (void)showHeader; 59 | - (void)showLoadCommands; 60 | 61 | @end 62 | 63 | extern NSString *CDErrorDomain_ClassDump; 64 | extern NSString *CDErrorKey_Exception; 65 | 66 | 67 | -------------------------------------------------------------------------------- /Source/CDClassDumpVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDTextClassDumpVisitor.h" 7 | 8 | @interface CDClassDumpVisitor : CDTextClassDumpVisitor 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDClassFrameworkVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDVisitor.h" 7 | 8 | // This builds up a dictionary mapping class names to a framework names. 9 | // It is only used by CDMultiFileVisitor to generate individual imports when creating separate header files. 10 | 11 | // Some protocols appear in multiple frameworks. This just records the last framework that contained a reference, which 12 | // produces incorrect results. For example, -r AppKit.framework, and Foundation.framework is processed before several 13 | // others, including Symbolication. 14 | 15 | // If we follow framework dependancies, the earliest reference to NSCopying is CoreFoundation, but NSCopying is really 16 | // defined in Foundation. 17 | 18 | // But it turns out that we can just use forward references for protocols. 19 | 20 | @interface CDClassFrameworkVisitor : CDVisitor 21 | 22 | // NSString (class name) -> NSString (framework name) 23 | @property (nonatomic, readonly) NSDictionary *frameworkNamesByClassName; 24 | 25 | // NSString (protocol name) -> NSString (framework name) 26 | @property (nonatomic, readonly) NSDictionary *frameworkNamesByProtocolName; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Source/CDClassFrameworkVisitor.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDClassFrameworkVisitor.h" 7 | 8 | #import "CDMachOFile.h" 9 | #import "CDOCClass.h" 10 | #import "CDObjectiveCProcessor.h" 11 | #import "CDSymbol.h" 12 | #import "CDLCDylib.h" 13 | #import "CDOCCategory.h" 14 | #import "CDOCClassReference.h" 15 | 16 | @interface CDClassFrameworkVisitor () 17 | @property (strong) NSString *frameworkName; 18 | @end 19 | 20 | #pragma mark - 21 | 22 | @implementation CDClassFrameworkVisitor 23 | { 24 | NSMutableDictionary *_frameworkNamesByClassName; 25 | NSMutableDictionary *_frameworkNamesByProtocolName; 26 | NSString *_frameworkName; 27 | } 28 | 29 | - (id)init; 30 | { 31 | if ((self = [super init])) { 32 | _frameworkNamesByClassName = [[NSMutableDictionary alloc] init]; 33 | _frameworkNamesByProtocolName = [[NSMutableDictionary alloc] init]; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | #pragma mark - 40 | 41 | - (void)willVisitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 42 | { 43 | self.frameworkName = processor.machOFile.importBaseName; 44 | } 45 | 46 | - (void)willVisitClass:(CDOCClass *)aClass; 47 | { 48 | [self addClassName:aClass.name referencedInFramework:self.frameworkName]; 49 | 50 | // We only need to add superclasses for external classes - classes defined in this binary will be visited on their own 51 | CDOCClassReference *superClassRef = [aClass superClassRef]; 52 | if ([superClassRef isExternalClass] && superClassRef.classSymbol != nil) { 53 | [self addClassForExternalSymbol:superClassRef.classSymbol]; 54 | } 55 | } 56 | 57 | - (void)willVisitProtocol:(CDOCProtocol *)protocol; 58 | { 59 | // TODO: (2012-02-28) Figure out what frameworks use each protocol, and try to pick the correct one. More difficult because, for example, NSCopying is found in many frameworks, and picking the last one isn't good enough. Perhaps a topological sort of the dependancies would be better. 60 | [self addProtocolName:protocol.name referencedInFramework:self.frameworkName]; 61 | } 62 | 63 | - (void)willVisitCategory:(CDOCCategory *)category; 64 | { 65 | CDOCClassReference *classRef = [category classRef]; 66 | if ([classRef isExternalClass] && classRef.classSymbol != nil) { 67 | [self addClassForExternalSymbol:classRef.classSymbol]; 68 | } 69 | } 70 | 71 | #pragma mark - 72 | 73 | - (void)addClassForExternalSymbol:(CDSymbol *)symbol; 74 | { 75 | NSString *frameworkName = CDImportNameForPath([[symbol dylibLoadCommand] path]); 76 | NSString *className = [CDSymbol classNameFromSymbolName:[symbol name]]; 77 | [self addClassName:className referencedInFramework:frameworkName]; 78 | } 79 | 80 | - (void)addClassName:(NSString *)name referencedInFramework:(NSString *)frameworkName; 81 | { 82 | if (name != nil && frameworkName != nil) 83 | _frameworkNamesByClassName[name] = frameworkName; 84 | } 85 | 86 | - (void)addProtocolName:(NSString *)name referencedInFramework:(NSString *)frameworkName; 87 | { 88 | if (name != nil && frameworkName != nil) 89 | _frameworkNamesByProtocolName[name] = frameworkName; 90 | } 91 | 92 | - (NSDictionary *)frameworkNamesByClassName; 93 | { 94 | return [_frameworkNamesByClassName copy]; 95 | } 96 | 97 | - (NSDictionary *)frameworkNamesByProtocolName; 98 | { 99 | return [_frameworkNamesByProtocolName copy]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Source/CDDataCursor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface CDDataCursor : NSObject 7 | 8 | - (id)initWithData:(NSData *)data; 9 | 10 | @property (readonly) NSData *data; 11 | - (const void *)bytes; 12 | 13 | @property (nonatomic, assign) NSUInteger offset; 14 | 15 | - (void)advanceByLength:(NSUInteger)length; 16 | - (NSUInteger)remaining; 17 | 18 | - (uint8_t)readByte; 19 | 20 | - (uint16_t)readLittleInt16; 21 | - (uint32_t)readLittleInt32; 22 | - (uint64_t)readLittleInt64; 23 | 24 | - (uint16_t)readBigInt16; 25 | - (uint32_t)readBigInt32; 26 | - (uint64_t)readBigInt64; 27 | 28 | - (float)readLittleFloat32; 29 | - (float)readBigFloat32; 30 | 31 | - (double)readLittleFloat64; 32 | //- (double)readBigFloat64; 33 | 34 | - (void)appendBytesOfLength:(NSUInteger)length intoData:(NSMutableData *)data; 35 | - (void)readBytesOfLength:(NSUInteger)length intoBuffer:(void *)buf; 36 | - (BOOL)isAtEnd; 37 | 38 | - (NSString *)readCString; 39 | - (NSString *)readStringOfLength:(NSUInteger)length encoding:(NSStringEncoding)encoding; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Source/CDExtensions.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDTopoSortNode.h" 7 | #import "NSArray-CDExtensions.h" 8 | #import "NSData-CDExtensions.h" 9 | #import "NSData-CDExtensions.h" 10 | #import "NSError-CDExtensions.h" 11 | #import "NSScanner-CDExtensions.h" 12 | #import "NSString-CDExtensions.h" 13 | -------------------------------------------------------------------------------- /Source/CDFatArch.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDFile.h" // For CDArch 7 | 8 | @class CDDataCursor; 9 | @class CDFatFile, CDMachOFile; 10 | 11 | @interface CDFatArch : NSObject 12 | 13 | - (id)initWithMachOFile:(CDMachOFile *)machOFile; 14 | - (id)initWithDataCursor:(CDDataCursor *)cursor; 15 | 16 | @property (assign) cpu_type_t cputype; 17 | @property (assign) cpu_subtype_t cpusubtype; 18 | @property (assign) uint32_t offset; 19 | @property (assign) uint32_t size; 20 | @property (assign) uint32_t align; 21 | 22 | @property (nonatomic, readonly) cpu_type_t maskedCPUType; 23 | @property (nonatomic, readonly) cpu_subtype_t maskedCPUSubtype; 24 | @property (nonatomic, readonly) BOOL uses64BitABI; 25 | @property (nonatomic, readonly) BOOL uses64BitLibraries; 26 | 27 | @property (weak) CDFatFile *fatFile; 28 | 29 | @property (nonatomic, readonly) CDArch arch; 30 | @property (nonatomic, readonly) NSString *archName; 31 | 32 | @property (nonatomic, readonly) CDMachOFile *machOFile; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Source/CDFatArch.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDFatArch.h" 7 | 8 | #include 9 | #import "CDDataCursor.h" 10 | #import "CDFatFile.h" 11 | #import "CDMachOFile.h" 12 | 13 | @implementation CDFatArch 14 | { 15 | __weak CDFatFile *_fatFile; 16 | 17 | // This is essentially struct fat_arch, but this way our property accessors can be synthesized. 18 | cpu_type_t _cputype; 19 | cpu_subtype_t _cpusubtype; 20 | uint32_t _offset; 21 | uint32_t _size; 22 | uint32_t _align; 23 | 24 | CDMachOFile *_machOFile; // Lazily create this. 25 | } 26 | 27 | - (id)initWithMachOFile:(CDMachOFile *)machOFile; 28 | { 29 | if ((self = [super init])) { 30 | _machOFile = machOFile; 31 | NSParameterAssert([machOFile.data length] < 0x100000000); 32 | 33 | _cputype = _machOFile.cputype; 34 | _cpusubtype = _machOFile.cpusubtype; 35 | _offset = 0; // Would be filled in when this is written to disk 36 | _size = (uint32_t)[_machOFile.data length]; 37 | _align = 12; // 2**12 = 4096 (0x1000) 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (id)initWithDataCursor:(CDDataCursor *)cursor; 44 | { 45 | if ((self = [super init])) { 46 | _cputype = [cursor readBigInt32]; 47 | _cpusubtype = [cursor readBigInt32]; 48 | _offset = [cursor readBigInt32]; 49 | _size = [cursor readBigInt32]; 50 | _align = [cursor readBigInt32]; 51 | 52 | //NSLog(@"self: %@", self); 53 | } 54 | 55 | return self; 56 | } 57 | 58 | #pragma mark - Debugging 59 | 60 | - (NSString *)description; 61 | { 62 | return [NSString stringWithFormat:@"64 bit ABI? %d, cputype: 0x%08x, cpusubtype: 0x%08x, offset: 0x%08x (%8u), size: 0x%08x (%8u), align: 2^%u (%x), arch name: %@", 63 | self.uses64BitABI, self.cputype, self.cpusubtype, self.offset, self.offset, self.size, self.size, 64 | self.align, 1 << self.align, self.archName]; 65 | } 66 | 67 | #pragma mark - 68 | 69 | - (cpu_type_t)maskedCPUType; 70 | { 71 | return self.cputype & ~CPU_ARCH_MASK; 72 | } 73 | 74 | - (cpu_subtype_t)maskedCPUSubtype; 75 | { 76 | return self.cpusubtype & ~CPU_SUBTYPE_MASK; 77 | } 78 | 79 | - (BOOL)uses64BitABI; 80 | { 81 | return CDArchUses64BitABI(self.arch); 82 | } 83 | 84 | - (BOOL)uses64BitLibraries; 85 | { 86 | return CDArchUses64BitLibraries(self.arch); 87 | } 88 | 89 | - (CDArch)arch; 90 | { 91 | CDArch arch = { self.cputype, self.cpusubtype }; 92 | 93 | return arch; 94 | } 95 | 96 | // Must not return nil. 97 | - (NSString *)archName; 98 | { 99 | return CDNameForCPUType(self.cputype, self.cpusubtype); 100 | } 101 | 102 | - (CDMachOFile *)machOFile; 103 | { 104 | if (_machOFile == nil) { 105 | NSData *data = [NSData dataWithBytesNoCopy:((uint8_t *)[self.fatFile.data bytes] + self.offset) length:self.size freeWhenDone:NO]; 106 | _machOFile = [[CDMachOFile alloc] initWithData:data filename:self.fatFile.filename searchPathState:self.fatFile.searchPathState]; 107 | } 108 | 109 | return _machOFile; 110 | } 111 | 112 | @end 113 | -------------------------------------------------------------------------------- /Source/CDFatFile.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDFile.h" 7 | 8 | @class CDFatArch; 9 | 10 | @interface CDFatFile : CDFile 11 | 12 | @property (readonly) NSMutableArray *arches; 13 | @property (nonatomic, readonly) NSArray *archNames; 14 | 15 | - (void)addArchitecture:(CDFatArch *)fatArch; 16 | - (BOOL)containsArchitecture:(CDArch)arch; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Source/CDFile.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #include // For cpu_type_t, cpu_subtype_t 7 | 8 | typedef struct { 9 | cpu_type_t cputype; 10 | cpu_subtype_t cpusubtype; 11 | } CDArch; 12 | 13 | @class CDMachOFile, CDSearchPathState; 14 | 15 | NSString *CDImportNameForPath(NSString *path); 16 | NSString *CDNameForCPUType(cpu_type_t cputype, cpu_subtype_t cpusubtype); 17 | CDArch CDArchFromName(NSString *name); 18 | BOOL CDArchUses64BitABI(CDArch arch); 19 | BOOL CDArchUses64BitLibraries(CDArch arch); 20 | 21 | @interface CDFile : NSObject 22 | 23 | // Returns CDFatFile or CDMachOFile 24 | + (id)fileWithContentsOfFile:(NSString *)filename searchPathState:(CDSearchPathState *)searchPathState; 25 | 26 | - (id)initWithData:(NSData *)data filename:(NSString *)filename searchPathState:(CDSearchPathState *)searchPathState; 27 | 28 | @property (readonly) NSString *filename; 29 | @property (readonly) NSData *data; 30 | @property (readonly) CDSearchPathState *searchPathState; 31 | 32 | - (BOOL)bestMatchForLocalArch:(CDArch *)oArchPtr; 33 | - (BOOL)bestMatchForArch:(CDArch *)ioArchPtr; 34 | - (CDMachOFile *)machOFileWithArch:(CDArch)arch; 35 | 36 | @property (nonatomic, readonly) NSString *architectureNameDescription; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Source/CDFindMethodVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDVisitor.h" 7 | 8 | // This limits the output to methods matching the search string. Some context is included, so that you can see which class, category, or protocol 9 | // contains the method. 10 | 11 | @interface CDFindMethodVisitor : CDVisitor 12 | 13 | @property (strong) NSString *searchString; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Source/CDLCBuildVersion.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCBuildVersion : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) NSString *buildVersionString; 11 | @property (nonatomic, readonly) NSArray *toolStrings; 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCDataInCode.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCLinkeditData.h" 7 | 8 | @interface CDLCDataInCode : CDLCLinkeditData 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCDataInCode.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCDataInCode.h" 7 | 8 | #import "CDMachOFile.h" 9 | 10 | @implementation CDLCDataInCode 11 | { 12 | } 13 | 14 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | { 16 | if ((self = [super initWithDataCursor:cursor])) { 17 | } 18 | 19 | return self; 20 | } 21 | 22 | #pragma mark - 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Source/CDLCDyldInfo.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCDyldInfo : CDLoadCommand 9 | 10 | - (NSString *)symbolNameForAddress:(NSUInteger)address; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCDylib.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCDylib : CDLoadCommand 9 | 10 | @property (readonly) NSString *path; 11 | @property (nonatomic, readonly) uint32_t timestamp; 12 | @property (nonatomic, readonly) uint32_t currentVersion; 13 | @property (nonatomic, readonly) uint32_t compatibilityVersion; 14 | 15 | @property (nonatomic, readonly) NSString *formattedCurrentVersion; 16 | @property (nonatomic, readonly) NSString *formattedCompatibilityVersion; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Source/CDLCDylib.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCDylib.h" 7 | 8 | #import "CDFatFile.h" 9 | #import "CDMachOFile.h" 10 | 11 | static NSString *CDDylibVersionString(uint32_t version) 12 | { 13 | return [NSString stringWithFormat:@"%d.%d.%d", version >> 16, (version >> 8) & 0xff, version & 0xff]; 14 | } 15 | 16 | @implementation CDLCDylib 17 | { 18 | struct dylib_command _dylibCommand; 19 | NSString *_path; 20 | } 21 | 22 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 23 | { 24 | if ((self = [super initWithDataCursor:cursor])) { 25 | _dylibCommand.cmd = [cursor readInt32]; 26 | _dylibCommand.cmdsize = [cursor readInt32]; 27 | 28 | _dylibCommand.dylib.name.offset = [cursor readInt32]; 29 | _dylibCommand.dylib.timestamp = [cursor readInt32]; 30 | _dylibCommand.dylib.current_version = [cursor readInt32]; 31 | _dylibCommand.dylib.compatibility_version = [cursor readInt32]; 32 | 33 | NSUInteger length = _dylibCommand.cmdsize - sizeof(_dylibCommand); 34 | //NSLog(@"expected length: %u", length); 35 | 36 | _path = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 37 | //NSLog(@"path: %@", path); 38 | } 39 | 40 | return self; 41 | } 42 | 43 | #pragma mark - 44 | 45 | - (uint32_t)cmd; 46 | { 47 | return _dylibCommand.cmd; 48 | } 49 | 50 | - (uint32_t)cmdsize; 51 | { 52 | return _dylibCommand.cmdsize; 53 | } 54 | 55 | - (uint32_t)timestamp; 56 | { 57 | return _dylibCommand.dylib.timestamp; 58 | } 59 | 60 | - (uint32_t)currentVersion; 61 | { 62 | return _dylibCommand.dylib.current_version; 63 | } 64 | 65 | - (uint32_t)compatibilityVersion; 66 | { 67 | return _dylibCommand.dylib.compatibility_version; 68 | } 69 | 70 | - (NSString *)formattedCurrentVersion; 71 | { 72 | return CDDylibVersionString(self.currentVersion); 73 | } 74 | 75 | - (NSString *)formattedCompatibilityVersion; 76 | { 77 | return CDDylibVersionString(self.compatibilityVersion); 78 | } 79 | 80 | #if 0 81 | - (NSString *)extraDescription; 82 | { 83 | return [NSString stringWithFormat:@"%@ (compatibility version %@, current version %@, timestamp %d [%@])", 84 | self.path, CDDylibVersionString(self.compatibilityVersion), CDDylibVersionString(self.currentVersion), 85 | self.timestamp, [NSDate dateWithTimeIntervalSince1970:self.timestamp]]; 86 | } 87 | #endif 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Source/CDLCDylinker.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCDylinker : CDLoadCommand 9 | 10 | @property (readonly) NSString *name; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCDylinker.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCDylinker.h" 7 | 8 | @implementation CDLCDylinker 9 | { 10 | struct dylinker_command _dylinkerCommand; 11 | NSString *_name; 12 | } 13 | 14 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | { 16 | if ((self = [super initWithDataCursor:cursor])) { 17 | _dylinkerCommand.cmd = [cursor readInt32]; 18 | _dylinkerCommand.cmdsize = [cursor readInt32]; 19 | 20 | _dylinkerCommand.name.offset = [cursor readInt32]; 21 | 22 | NSUInteger length = _dylinkerCommand.cmdsize - sizeof(_dylinkerCommand); 23 | //NSLog(@"expected length: %u", length); 24 | 25 | _name = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 26 | //NSLog(@"name: %@", name); 27 | } 28 | 29 | return self; 30 | } 31 | 32 | #pragma mark - 33 | 34 | - (uint32_t)cmd; 35 | { 36 | return _dylinkerCommand.cmd; 37 | } 38 | 39 | - (uint32_t)cmdsize; 40 | { 41 | return _dylinkerCommand.cmdsize; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Source/CDLCDynamicSymbolTable.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @class CDRelocationInfo; 9 | 10 | @interface CDLCDynamicSymbolTable : CDLoadCommand 11 | 12 | - (void)loadSymbols; 13 | 14 | - (CDRelocationInfo *)relocationEntryWithOffset:(NSUInteger)offset; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Source/CDLCEncryptionInfo.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCEncryptionInfo : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) uint32_t cryptoff; 11 | @property (nonatomic, readonly) uint32_t cryptsize; 12 | @property (nonatomic, readonly) uint32_t cryptid; 13 | 14 | @property (nonatomic, readonly) BOOL isEncrypted; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Source/CDLCEncryptionInfo.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCEncryptionInfo.h" 7 | 8 | // This is used on iOS. 9 | 10 | @implementation CDLCEncryptionInfo 11 | { 12 | struct encryption_info_command_64 _encryptionInfoCommand; 13 | } 14 | 15 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 16 | { 17 | if ((self = [super initWithDataCursor:cursor])) { 18 | _encryptionInfoCommand.cmd = [cursor readInt32]; 19 | _encryptionInfoCommand.cmdsize = [cursor readInt32]; 20 | 21 | _encryptionInfoCommand.cryptoff = [cursor readInt32]; 22 | _encryptionInfoCommand.cryptsize = [cursor readInt32]; 23 | _encryptionInfoCommand.cryptid = [cursor readInt32]; 24 | if (_encryptionInfoCommand.cmd == LC_ENCRYPTION_INFO_64) { 25 | _encryptionInfoCommand.pad = [cursor readInt32]; 26 | } 27 | } 28 | 29 | return self; 30 | } 31 | 32 | #pragma mark - 33 | 34 | - (uint32_t)cmd; 35 | { 36 | return _encryptionInfoCommand.cmd; 37 | } 38 | 39 | - (uint32_t)cmdsize; 40 | { 41 | return _encryptionInfoCommand.cmdsize; 42 | } 43 | 44 | - (uint32_t)cryptoff; 45 | { 46 | return _encryptionInfoCommand.cryptoff; 47 | } 48 | 49 | - (uint32_t)cryptsize; 50 | { 51 | return _encryptionInfoCommand.cryptsize; 52 | } 53 | 54 | - (uint32_t)cryptid; 55 | { 56 | return _encryptionInfoCommand.cryptid; 57 | } 58 | 59 | - (BOOL)isEncrypted; 60 | { 61 | return _encryptionInfoCommand.cryptid != 0; 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Source/CDLCFunctionStarts.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCLinkeditData.h" 7 | 8 | @interface CDLCFunctionStarts : CDLCLinkeditData 9 | 10 | @property (nonatomic, readonly) NSArray *functionStarts; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCFunctionStarts.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCFunctionStarts.h" 7 | 8 | #import "ULEB128.h" 9 | 10 | @implementation CDLCFunctionStarts 11 | { 12 | NSArray *_functionStarts; 13 | } 14 | 15 | #pragma mark - 16 | 17 | - (NSArray *)functionStarts; 18 | { 19 | if (_functionStarts == nil) { 20 | NSData *functionStartsData = [self linkeditData]; 21 | const uint8_t *start = (uint8_t *)[functionStartsData bytes]; 22 | const uint8_t *end = start + [functionStartsData length]; 23 | uint64_t startAddress; 24 | uint64_t previousAddress = 0; 25 | NSMutableArray *functionStarts = [[NSMutableArray alloc] init]; 26 | while ((startAddress = read_uleb128(&start, end))) { 27 | [functionStarts addObject:@(startAddress + previousAddress)]; 28 | previousAddress += startAddress; 29 | } 30 | _functionStarts = [functionStarts copy]; 31 | } 32 | return _functionStarts; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Source/CDLCLinkeditData.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCLinkeditData : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) NSData *linkeditData; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCLinkeditData.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCLinkeditData.h" 7 | 8 | #import "CDMachOFile.h" 9 | 10 | @implementation CDLCLinkeditData 11 | { 12 | struct linkedit_data_command _linkeditDataCommand; 13 | NSData *_linkeditData; 14 | } 15 | 16 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 17 | { 18 | if ((self = [super initWithDataCursor:cursor])) { 19 | _linkeditDataCommand.cmd = [cursor readInt32]; 20 | _linkeditDataCommand.cmdsize = [cursor readInt32]; 21 | 22 | _linkeditDataCommand.dataoff = [cursor readInt32]; 23 | _linkeditDataCommand.datasize = [cursor readInt32]; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | #pragma mark - 30 | 31 | - (uint32_t)cmd; 32 | { 33 | return _linkeditDataCommand.cmd; 34 | } 35 | 36 | - (uint32_t)cmdsize; 37 | { 38 | return _linkeditDataCommand.cmdsize; 39 | } 40 | 41 | - (NSData *)linkeditData; 42 | { 43 | if (_linkeditData == NULL) { 44 | _linkeditData = [[NSData alloc] initWithBytes:[self.machOFile bytesAtOffset:_linkeditDataCommand.dataoff] length:_linkeditDataCommand.datasize]; 45 | } 46 | 47 | return _linkeditData; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Source/CDLCMain.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCMain : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCMain.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCMain.h" 7 | 8 | @implementation CDLCMain 9 | { 10 | struct entry_point_command _entryPointCommand; 11 | } 12 | 13 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 14 | { 15 | if ((self = [super initWithDataCursor:cursor])) { 16 | _entryPointCommand.cmd = [cursor readInt32]; 17 | _entryPointCommand.cmdsize = [cursor readInt32]; 18 | _entryPointCommand.entryoff = [cursor readInt64]; 19 | _entryPointCommand.stacksize = [cursor readInt64]; 20 | } 21 | 22 | return self; 23 | } 24 | 25 | #pragma mark - 26 | 27 | - (uint32_t)cmd; 28 | { 29 | return _entryPointCommand.cmd; 30 | } 31 | 32 | - (uint32_t)cmdsize; 33 | { 34 | return _entryPointCommand.cmdsize; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Source/CDLCPrebindChecksum.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCPrebindChecksum : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) uint32_t cksum; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCPrebindChecksum.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCPrebindChecksum.h" 7 | 8 | @implementation CDLCPrebindChecksum 9 | { 10 | struct prebind_cksum_command _prebindChecksumCommand; 11 | } 12 | 13 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 14 | { 15 | if ((self = [super initWithDataCursor:cursor])) { 16 | _prebindChecksumCommand.cmd = [cursor readInt32]; 17 | _prebindChecksumCommand.cmdsize = [cursor readInt32]; 18 | _prebindChecksumCommand.cksum = [cursor readInt32]; 19 | } 20 | 21 | return self; 22 | } 23 | 24 | #pragma mark - 25 | 26 | - (uint32_t)cmd; 27 | { 28 | return _prebindChecksumCommand.cmd; 29 | } 30 | 31 | - (uint32_t)cmdsize; 32 | { 33 | return _prebindChecksumCommand.cmdsize; 34 | } 35 | 36 | - (uint32_t)cksum; 37 | { 38 | return _prebindChecksumCommand.cksum; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Source/CDLCPreboundDylib.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCPreboundDylib : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCPreboundDylib.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCPreboundDylib.h" 7 | 8 | #import "CDFatFile.h" 9 | #import "CDMachOFile.h" 10 | 11 | @implementation CDLCPreboundDylib 12 | { 13 | struct prebound_dylib_command _preboundDylibCommand; 14 | } 15 | 16 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 17 | { 18 | if ((self = [super initWithDataCursor:cursor])) { 19 | //NSLog(@"current offset: %u", [cursor offset]); 20 | _preboundDylibCommand.cmd = [cursor readInt32]; 21 | _preboundDylibCommand.cmdsize = [cursor readInt32]; 22 | //NSLog(@"cmdsize: %u", preboundDylibCommand.cmdsize); 23 | 24 | _preboundDylibCommand.name.offset = [cursor readInt32]; 25 | _preboundDylibCommand.nmodules = [cursor readInt32]; 26 | _preboundDylibCommand.linked_modules.offset = [cursor readInt32]; 27 | 28 | if (_preboundDylibCommand.cmdsize > 20) { 29 | // Don't need this info right now. 30 | [cursor advanceByLength:_preboundDylibCommand.cmdsize - 20]; 31 | } 32 | } 33 | 34 | return self; 35 | } 36 | 37 | #pragma mark - 38 | 39 | - (uint32_t)cmd; 40 | { 41 | return _preboundDylibCommand.cmd; 42 | } 43 | 44 | - (uint32_t)cmdsize; 45 | { 46 | return _preboundDylibCommand.cmdsize; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Source/CDLCRoutines32.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCRoutines32 : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCRoutines32.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCRoutines32.h" 7 | 8 | @implementation CDLCRoutines32 9 | { 10 | struct routines_command _routinesCommand; 11 | } 12 | 13 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 14 | { 15 | if ((self = [super initWithDataCursor:cursor])) { 16 | _routinesCommand.cmd = [cursor readInt32]; 17 | _routinesCommand.cmdsize = [cursor readInt32]; 18 | 19 | _routinesCommand.init_address = [cursor readInt32]; 20 | _routinesCommand.init_module = [cursor readInt32]; 21 | _routinesCommand.reserved1 = [cursor readInt32]; 22 | _routinesCommand.reserved2 = [cursor readInt32]; 23 | _routinesCommand.reserved3 = [cursor readInt32]; 24 | _routinesCommand.reserved4 = [cursor readInt32]; 25 | _routinesCommand.reserved5 = [cursor readInt32]; 26 | _routinesCommand.reserved6 = [cursor readInt32]; 27 | } 28 | 29 | return self; 30 | } 31 | 32 | #pragma mark - 33 | 34 | - (uint32_t)cmd; 35 | { 36 | return _routinesCommand.cmd; 37 | } 38 | 39 | - (uint32_t)cmdsize; 40 | { 41 | return _routinesCommand.cmdsize; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Source/CDLCRoutines64.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCRoutines64 : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCRoutines64.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCRoutines64.h" 7 | 8 | @implementation CDLCRoutines64 9 | { 10 | struct routines_command_64 _routinesCommand; 11 | } 12 | 13 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 14 | { 15 | if ((self = [super initWithDataCursor:cursor])) { 16 | _routinesCommand.cmd = [cursor readInt32]; 17 | _routinesCommand.cmdsize = [cursor readInt32]; 18 | 19 | _routinesCommand.init_address = [cursor readInt64]; 20 | _routinesCommand.init_module = [cursor readInt64]; 21 | _routinesCommand.reserved1 = [cursor readInt64]; 22 | _routinesCommand.reserved2 = [cursor readInt64]; 23 | _routinesCommand.reserved3 = [cursor readInt64]; 24 | _routinesCommand.reserved4 = [cursor readInt64]; 25 | _routinesCommand.reserved5 = [cursor readInt64]; 26 | _routinesCommand.reserved6 = [cursor readInt64]; 27 | } 28 | 29 | return self; 30 | } 31 | 32 | #pragma mark - 33 | 34 | - (uint32_t)cmd; 35 | { 36 | return _routinesCommand.cmd; 37 | } 38 | 39 | - (uint32_t)cmdsize; 40 | { 41 | return _routinesCommand.cmdsize; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Source/CDLCRunPath.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCRunPath : CDLoadCommand 9 | 10 | @property (readonly) NSString *path; 11 | @property (nonatomic, readonly) NSString *resolvedRunPath; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Source/CDLCRunPath.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCRunPath.h" 7 | 8 | #import "CDMachOFile.h" 9 | #import "CDSearchPathState.h" 10 | 11 | @implementation CDLCRunPath 12 | { 13 | struct rpath_command _rpathCommand; 14 | NSString *_path; 15 | } 16 | 17 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 18 | { 19 | if ((self = [super initWithDataCursor:cursor])) { 20 | _rpathCommand.cmd = [cursor readInt32]; 21 | _rpathCommand.cmdsize = [cursor readInt32]; 22 | 23 | _rpathCommand.path.offset = [cursor readInt32]; 24 | 25 | NSUInteger length = _rpathCommand.cmdsize - sizeof(_rpathCommand); 26 | //NSLog(@"expected length: %u", length); 27 | 28 | _path = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 29 | //NSLog(@"path: %@", _path); 30 | } 31 | 32 | return self; 33 | } 34 | 35 | #pragma mark - 36 | 37 | - (uint32_t)cmd; 38 | { 39 | return _rpathCommand.cmd; 40 | } 41 | 42 | - (uint32_t)cmdsize; 43 | { 44 | return _rpathCommand.cmdsize; 45 | } 46 | 47 | - (NSString *)resolvedRunPath; 48 | { 49 | NSString *loaderPathPrefix = @"@loader_path"; 50 | NSString *executablePathPrefix = @"@executable_path"; 51 | 52 | if ([self.path hasPrefix:loaderPathPrefix]) { 53 | NSString *loaderPath = [self.machOFile.filename stringByDeletingLastPathComponent]; 54 | NSString *str = [[self.path stringByReplacingOccurrencesOfString:loaderPathPrefix withString:loaderPath] stringByStandardizingPath]; 55 | 56 | return str; 57 | } 58 | 59 | if ([self.path hasPrefix:executablePathPrefix]) { 60 | NSString *str = @""; 61 | NSString *executablePath = self.machOFile.searchPathState.executablePath; 62 | if (executablePath) 63 | str = [[self.path stringByReplacingOccurrencesOfString:executablePathPrefix withString:executablePath] stringByStandardizingPath]; 64 | 65 | return str; 66 | } 67 | 68 | return self.path; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Source/CDLCSegment.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @class CDSection; 9 | 10 | #define CDSegmentProtectedMagic_None 0 11 | #define CDSegmentProtectedMagic_AES 0xc2286295 12 | #define CDSegmentProtectedMagic_Blowfish 0x2e69cf40 13 | 14 | typedef enum : NSUInteger { 15 | CDSegmentEncryptionType_None = 0, 16 | CDSegmentEncryptionType_AES = 1, // 10.5 and earlier (AES) 17 | CDSegmentEncryptionType_Blowfish = 2, // 10.6 (Blowfish) 18 | CDSegmentEncryptionType_Unknown 19 | } CDSegmentEncryptionType; 20 | 21 | extern NSString *CDSegmentEncryptionTypeName(CDSegmentEncryptionType type); 22 | 23 | @interface CDLCSegment : CDLoadCommand 24 | 25 | @property (strong) NSString *name; 26 | @property (strong) NSArray *sections; 27 | 28 | @property (nonatomic, readonly) NSUInteger vmaddr; 29 | @property (nonatomic, readonly) NSUInteger fileoff; 30 | @property (nonatomic, readonly) NSUInteger filesize; 31 | @property (nonatomic, readonly) vm_prot_t initprot; 32 | @property (nonatomic, readonly) uint32_t flags; 33 | @property (nonatomic, readonly) BOOL isProtected; 34 | 35 | @property (nonatomic, readonly) CDSegmentEncryptionType encryptionType; 36 | @property (nonatomic, readonly) BOOL canDecrypt; 37 | 38 | - (NSString *)flagDescription; 39 | 40 | - (BOOL)containsAddress:(NSUInteger)address; 41 | - (CDSection *)sectionContainingAddress:(NSUInteger)address; 42 | - (CDSection *)sectionWithName:(NSString *)name; 43 | - (NSUInteger)fileOffsetForAddress:(NSUInteger)address; 44 | - (NSUInteger)segmentOffsetForAddress:(NSUInteger)address; 45 | 46 | - (void)writeSectionData; 47 | 48 | - (NSData *)decryptedData; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Source/CDLCSourceVersion.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCSourceVersion : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) NSString *sourceVersionString; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCSourceVersion.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCSourceVersion.h" 7 | 8 | #import "CDMachOFile.h" 9 | 10 | @implementation CDLCSourceVersion 11 | { 12 | struct source_version_command _sourceVersionCommand; 13 | } 14 | 15 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 16 | { 17 | if ((self = [super initWithDataCursor:cursor])) { 18 | _sourceVersionCommand.cmd = [cursor readInt32]; 19 | _sourceVersionCommand.cmdsize = [cursor readInt32]; 20 | _sourceVersionCommand.version = [cursor readInt64]; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | #pragma mark - 27 | 28 | - (uint32_t)cmd; 29 | { 30 | return _sourceVersionCommand.cmd; 31 | } 32 | 33 | - (uint32_t)cmdsize; 34 | { 35 | return _sourceVersionCommand.cmdsize; 36 | } 37 | 38 | - (NSString *)sourceVersionString; 39 | { 40 | // A.B.C.D.E packed as a24.b10.c10.d10.e10 41 | uint32_t a = _sourceVersionCommand.version >> 40; 42 | uint32_t b = (_sourceVersionCommand.version >> 30) & 0x3ff; 43 | uint32_t c = (_sourceVersionCommand.version >> 20) & 0x3ff; 44 | uint32_t d = (_sourceVersionCommand.version >> 10) & 0x3ff; 45 | uint32_t e = _sourceVersionCommand.version & 0x3ff; 46 | 47 | return [NSString stringWithFormat:@"%u.%u.%u.%u.%u", a, b, c, d, e]; 48 | } 49 | 50 | - (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose; 51 | { 52 | [super appendToString:resultString verbose:isVerbose]; 53 | 54 | [resultString appendFormat:@" Source version: %@\n", self.sourceVersionString]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Source/CDLCSubClient.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCSubClient : CDLoadCommand 9 | 10 | @property (readonly) NSString *name; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCSubClient.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCSubClient.h" 7 | 8 | @implementation CDLCSubClient 9 | { 10 | struct sub_client_command _command; 11 | NSString *_name; 12 | } 13 | 14 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | { 16 | if ((self = [super initWithDataCursor:cursor])) { 17 | _command.cmd = [cursor readInt32]; 18 | _command.cmdsize = [cursor readInt32]; 19 | 20 | uint32_t strOffset = [cursor readInt32]; 21 | NSParameterAssert(strOffset == 12); 22 | 23 | NSUInteger length = _command.cmdsize - sizeof(_command); 24 | //NSLog(@"expected length: %u", length); 25 | 26 | _name = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 27 | //NSLog(@"name: %@", _name); 28 | } 29 | 30 | return self; 31 | } 32 | 33 | #pragma mark - 34 | 35 | - (uint32_t)cmd; 36 | { 37 | return _command.cmd; 38 | } 39 | 40 | - (uint32_t)cmdsize; 41 | { 42 | return _command.cmdsize; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Source/CDLCSubFramework.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCSubFramework : CDLoadCommand 9 | 10 | @property (readonly) NSString *name; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCSubFramework.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCSubFramework.h" 7 | 8 | @implementation CDLCSubFramework 9 | { 10 | struct sub_framework_command _command; 11 | NSString *_name; 12 | } 13 | 14 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | { 16 | if ((self = [super initWithDataCursor:cursor])) { 17 | _command.cmd = [cursor readInt32]; 18 | _command.cmdsize = [cursor readInt32]; 19 | 20 | uint32_t strOffset = [cursor readInt32]; 21 | NSParameterAssert(strOffset == 12); 22 | 23 | NSUInteger length = _command.cmdsize - sizeof(_command); 24 | //NSLog(@"expected length: %u", length); 25 | 26 | _name = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 27 | //NSLog(@"name: %@", _name); 28 | } 29 | 30 | return self; 31 | } 32 | 33 | #pragma mark - 34 | 35 | - (uint32_t)cmd; 36 | { 37 | return _command.cmd; 38 | } 39 | 40 | - (uint32_t)cmdsize; 41 | { 42 | return _command.cmdsize; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Source/CDLCSubLibrary.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCSubLibrary : CDLoadCommand 9 | 10 | @property (readonly) NSString *name; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCSubLibrary.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCSubLibrary.h" 7 | 8 | @implementation CDLCSubLibrary 9 | { 10 | struct sub_library_command _command; 11 | NSString *_name; 12 | } 13 | 14 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | { 16 | if ((self = [super initWithDataCursor:cursor])) { 17 | _command.cmd = [cursor readInt32]; 18 | _command.cmdsize = [cursor readInt32]; 19 | 20 | NSUInteger length = _command.cmdsize - sizeof(_command); 21 | //NSLog(@"expected length: %u", length); 22 | 23 | _name = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 24 | //NSLog(@"name: %@", _name); 25 | } 26 | 27 | return self; 28 | } 29 | 30 | #pragma mark - 31 | 32 | - (uint32_t)cmd; 33 | { 34 | return _command.cmd; 35 | } 36 | 37 | - (uint32_t)cmdsize; 38 | { 39 | return _command.cmdsize; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Source/CDLCSubUmbrella.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCSubUmbrella : CDLoadCommand 9 | 10 | @property (readonly) NSString *name; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCSubUmbrella.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCSubUmbrella.h" 7 | 8 | @implementation CDLCSubUmbrella 9 | { 10 | struct sub_umbrella_command _command; 11 | NSString *_name; 12 | } 13 | 14 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | { 16 | if ((self = [super initWithDataCursor:cursor])) { 17 | _command.cmd = [cursor readInt32]; 18 | _command.cmdsize = [cursor readInt32]; 19 | 20 | NSUInteger length = _command.cmdsize - sizeof(_command); 21 | //NSLog(@"expected length: %u", length); 22 | 23 | _name = [cursor readStringOfLength:length encoding:NSASCIIStringEncoding]; 24 | //NSLog(@"name: %@", _name); 25 | } 26 | 27 | return self; 28 | } 29 | 30 | #pragma mark - 31 | 32 | - (uint32_t)cmd; 33 | { 34 | return _command.cmd; 35 | } 36 | 37 | - (uint32_t)cmdsize; 38 | { 39 | return _command.cmdsize; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Source/CDLCSymbolTable.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @class CDSymbol; 9 | 10 | @interface CDLCSymbolTable : CDLoadCommand 11 | 12 | - (void)loadSymbols; 13 | 14 | @property (nonatomic, readonly) uint32_t symoff; 15 | @property (nonatomic, readonly) uint32_t nsyms; 16 | @property (nonatomic, readonly) uint32_t stroff; 17 | @property (nonatomic, readonly) uint32_t strsize; 18 | 19 | @property (nonatomic, readonly) NSUInteger baseAddress; 20 | @property (nonatomic, readonly) NSArray *symbols; 21 | 22 | - (CDSymbol *)symbolForClassName:(NSString *)className; 23 | - (CDSymbol *)symbolForExternalClassName:(NSString *)className; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Source/CDLCTwoLevelHints.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCTwoLevelHints : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCTwoLevelHints.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCTwoLevelHints.h" 7 | 8 | #import "CDMachOFile.h" 9 | 10 | @implementation CDLCTwoLevelHints 11 | { 12 | struct twolevel_hints_command _hintsCommand; 13 | } 14 | 15 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 16 | { 17 | if ((self = [super initWithDataCursor:cursor])) { 18 | _hintsCommand.cmd = [cursor readInt32]; 19 | _hintsCommand.cmdsize = [cursor readInt32]; 20 | _hintsCommand.offset = [cursor readInt32]; 21 | _hintsCommand.nhints = [cursor readInt32]; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | #pragma mark - 28 | 29 | - (uint32_t)cmd; 30 | { 31 | return _hintsCommand.cmd; 32 | } 33 | 34 | - (uint32_t)cmdsize; 35 | { 36 | return _hintsCommand.cmdsize; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Source/CDLCUUID.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCUUID : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) NSUUID *UUID; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/CDLCUUID.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCUUID.h" 7 | 8 | #import "CDMachOFile.h" 9 | 10 | @implementation CDLCUUID 11 | { 12 | struct uuid_command _uuidCommand; 13 | 14 | NSUUID *_UUID; 15 | } 16 | 17 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 18 | { 19 | if ((self = [super initWithDataCursor:cursor])) { 20 | _uuidCommand.cmd = [cursor readInt32]; 21 | _uuidCommand.cmdsize = [cursor readInt32]; 22 | for (NSUInteger index = 0; index < sizeof(_uuidCommand.uuid); index++) { 23 | _uuidCommand.uuid[index] = [cursor readByte]; 24 | } 25 | _UUID = [[NSUUID alloc] initWithUUIDBytes:_uuidCommand.uuid]; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | #pragma mark - 32 | 33 | - (uint32_t)cmd; 34 | { 35 | return _uuidCommand.cmd; 36 | } 37 | 38 | - (uint32_t)cmdsize; 39 | { 40 | return _uuidCommand.cmdsize; 41 | } 42 | 43 | - (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose; 44 | { 45 | [super appendToString:resultString verbose:isVerbose]; 46 | 47 | [resultString appendString:@" uuid "]; 48 | [resultString appendString:[self.UUID UUIDString]]; 49 | [resultString appendString:@"\n"]; 50 | } 51 | 52 | - (NSString *)extraDescription; 53 | { 54 | return [self.UUID UUIDString]; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Source/CDLCUnixThread.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCUnixThread : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCUnixThread.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCUnixThread.h" 7 | 8 | // For now, this is all I need. There is no data in here sensitive to its position in the file. 9 | 10 | @implementation CDLCUnixThread 11 | { 12 | struct load_command _loadCommand; 13 | 14 | NSData *_commandData; 15 | } 16 | 17 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 18 | { 19 | if ((self = [super initWithDataCursor:cursor])) { 20 | _loadCommand.cmd = [cursor readInt32]; 21 | _loadCommand.cmdsize = [cursor readInt32]; 22 | 23 | if (_loadCommand.cmdsize > 8) { 24 | NSMutableData *commandData = [[NSMutableData alloc] init]; 25 | [cursor appendBytesOfLength:_loadCommand.cmdsize - 8 intoData:commandData]; 26 | _commandData = [commandData copy]; 27 | } else { 28 | _commandData = nil; 29 | } 30 | } 31 | 32 | return self; 33 | } 34 | 35 | #pragma mark - 36 | 37 | - (uint32_t)cmd; 38 | { 39 | return _loadCommand.cmd; 40 | } 41 | 42 | - (uint32_t)cmdsize; 43 | { 44 | return _loadCommand.cmdsize; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Source/CDLCUnknown.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCUnknown : CDLoadCommand 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDLCUnknown.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCUnknown.h" 7 | 8 | static BOOL debug = NO; 9 | 10 | @implementation CDLCUnknown 11 | { 12 | struct load_command _loadCommand; 13 | 14 | NSData *_commandData; 15 | } 16 | 17 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 18 | { 19 | if ((self = [super initWithDataCursor:cursor])) { 20 | if (debug) NSLog(@"offset: %lu", [cursor offset]); 21 | _loadCommand.cmd = [cursor readInt32]; 22 | _loadCommand.cmdsize = [cursor readInt32]; 23 | if (debug) NSLog(@"cmdsize: %u", _loadCommand.cmdsize); 24 | 25 | if (_loadCommand.cmdsize > 8) { 26 | NSMutableData *commandData = [[NSMutableData alloc] init]; 27 | [cursor appendBytesOfLength:_loadCommand.cmdsize - 8 intoData:commandData]; 28 | _commandData = [commandData copy]; 29 | } else { 30 | _commandData = nil; 31 | } 32 | } 33 | 34 | return self; 35 | } 36 | 37 | #pragma mark - 38 | 39 | - (uint32_t)cmd; 40 | { 41 | return _loadCommand.cmd; 42 | } 43 | 44 | - (uint32_t)cmdsize; 45 | { 46 | return _loadCommand.cmdsize; 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Source/CDLCVersionMinimum.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLoadCommand.h" 7 | 8 | @interface CDLCVersionMinimum : CDLoadCommand 9 | 10 | @property (nonatomic, readonly) NSString *minimumVersionString; 11 | @property (nonatomic, readonly) NSString *SDKVersionString; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Source/CDLCVersionMinimum.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDLCVersionMinimum.h" 7 | 8 | #import "CDMachOFile.h" 9 | 10 | @implementation CDLCVersionMinimum 11 | { 12 | struct version_min_command _versionMinCommand; 13 | } 14 | 15 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 16 | { 17 | if ((self = [super initWithDataCursor:cursor])) { 18 | _versionMinCommand.cmd = [cursor readInt32]; 19 | _versionMinCommand.cmdsize = [cursor readInt32]; 20 | _versionMinCommand.version = [cursor readInt32]; 21 | _versionMinCommand.sdk = [cursor readInt32]; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | #pragma mark - 28 | 29 | - (uint32_t)cmd; 30 | { 31 | return _versionMinCommand.cmd; 32 | } 33 | 34 | - (uint32_t)cmdsize; 35 | { 36 | return _versionMinCommand.cmdsize; 37 | } 38 | 39 | - (NSString *)minimumVersionString; 40 | { 41 | uint32_t x = (_versionMinCommand.version >> 16); 42 | uint32_t y = (_versionMinCommand.version >> 8) & 0xff; 43 | uint32_t z = _versionMinCommand.version & 0xff; 44 | 45 | return [NSString stringWithFormat:@"%u.%u.%u", x, y, z]; 46 | } 47 | 48 | - (NSString *)SDKVersionString; 49 | { 50 | uint32_t x = (_versionMinCommand.sdk >> 16); 51 | uint32_t y = (_versionMinCommand.sdk >> 8) & 0xff; 52 | uint32_t z = _versionMinCommand.sdk & 0xff; 53 | 54 | return [NSString stringWithFormat:@"%u.%u.%u", x, y, z]; 55 | } 56 | 57 | - (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose; 58 | { 59 | [super appendToString:resultString verbose:isVerbose]; 60 | 61 | [resultString appendFormat:@" Minimum version: %@\n", self.minimumVersionString]; 62 | [resultString appendFormat:@" SDK version: %@\n", self.SDKVersionString]; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Source/CDLoadCommand.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | // Importing these here saves us from importing them in the implementation of every load command. 7 | #include 8 | #import "CDMachOFileDataCursor.h" 9 | 10 | @class CDMachOFile; 11 | 12 | @interface CDLoadCommand : NSObject 13 | 14 | + (id)loadCommandWithDataCursor:(CDMachOFileDataCursor *)cursor; 15 | 16 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor; 17 | 18 | - (NSString *)extraDescription; 19 | 20 | @property (weak, readonly) CDMachOFile *machOFile; 21 | @property (readonly) NSUInteger commandOffset; 22 | 23 | @property (nonatomic, readonly) uint32_t cmd; 24 | @property (nonatomic, readonly) uint32_t cmdsize; 25 | @property (nonatomic, readonly) BOOL mustUnderstandToExecute; 26 | 27 | @property (nonatomic, readonly) NSString *commandName; 28 | 29 | - (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose; 30 | 31 | - (void)machOFileDidReadLoadCommands:(CDMachOFile *)machOFile; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Source/CDMachOFile.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDFile.h" 7 | 8 | #include // For cpu_type_t, cpu_subtype_t 9 | #include 10 | 11 | typedef enum : NSUInteger { 12 | CDByteOrder_LittleEndian = 0, 13 | CDByteOrder_BigEndian = 1, 14 | } CDByteOrder; 15 | 16 | @class CDLCSegment; 17 | @class CDLCBuildVersion, CDLCDyldInfo, CDLCDylib, CDMachOFile, CDLCSymbolTable, CDLCDynamicSymbolTable, CDLCVersionMinimum, CDLCSourceVersion; 18 | 19 | @interface CDMachOFile : CDFile 20 | 21 | @property (readonly) CDByteOrder byteOrder; 22 | 23 | @property (readonly) uint32_t magic; 24 | @property (assign) cpu_type_t cputype; 25 | @property (assign) cpu_subtype_t cpusubtype; 26 | @property (readonly) uint32_t filetype; 27 | @property (readonly) uint32_t flags; 28 | 29 | @property (nonatomic, readonly) cpu_type_t maskedCPUType; 30 | @property (nonatomic, readonly) cpu_subtype_t maskedCPUSubtype; 31 | 32 | @property (readonly) NSArray *loadCommands; 33 | @property (readonly) NSArray *dylibLoadCommands; 34 | @property (readonly) NSArray *segments; 35 | @property (readonly) NSArray *runPaths; 36 | @property (readonly) NSArray *runPathCommands; 37 | @property (readonly) NSArray *dyldEnvironment; 38 | @property (readonly) NSArray *reExportedDylibs; 39 | 40 | @property (strong) CDLCSymbolTable *symbolTable; 41 | @property (strong) CDLCDynamicSymbolTable *dynamicSymbolTable; 42 | @property (strong) CDLCDyldInfo *dyldInfo; 43 | @property (strong) CDLCDylib *dylibIdentifier; 44 | @property (strong) CDLCVersionMinimum *minVersionMacOSX; 45 | @property (strong) CDLCVersionMinimum *minVersionIOS; 46 | @property (strong) CDLCSourceVersion *sourceVersion; 47 | @property (strong) CDLCBuildVersion *buildVersion; 48 | 49 | @property (readonly) BOOL uses64BitABI; 50 | - (NSUInteger)ptrSize; 51 | 52 | - (NSString *)filetypeDescription; 53 | - (NSString *)flagDescription; 54 | 55 | - (CDLCSegment *)dataConstSegment; 56 | - (CDLCSegment *)segmentWithName:(NSString *)segmentName; 57 | - (CDLCSegment *)segmentContainingAddress:(NSUInteger)address; 58 | - (NSString *)stringAtAddress:(NSUInteger)address; 59 | 60 | - (NSUInteger)dataOffsetForAddress:(NSUInteger)address; 61 | 62 | - (const void *)bytes; 63 | - (const void *)bytesAtOffset:(NSUInteger)offset; 64 | 65 | @property (nonatomic, readonly) NSString *importBaseName; 66 | 67 | @property (nonatomic, readonly) BOOL isEncrypted; 68 | @property (nonatomic, readonly) BOOL hasProtectedSegments; 69 | @property (nonatomic, readonly) BOOL canDecryptAllSegments; 70 | 71 | - (NSString *)loadCommandString:(BOOL)isVerbose; 72 | - (NSString *)headerString:(BOOL)isVerbose; 73 | 74 | @property (nonatomic, readonly) NSUUID *UUID; 75 | @property (nonatomic, readonly) NSString *archName; 76 | 77 | - (Class)processorClass; 78 | - (void)logInfoForAddress:(NSUInteger)address; 79 | 80 | - (NSString *)externalClassNameForAddress:(NSUInteger)address; 81 | - (BOOL)hasRelocationEntryForAddress:(NSUInteger)address; 82 | 83 | // Checks compressed dyld info on 10.6 or later. 84 | - (BOOL)hasRelocationEntryForAddress2:(NSUInteger)address; 85 | - (NSString *)externalClassNameForAddress2:(NSUInteger)address; 86 | 87 | - (CDLCDylib *)dylibLoadCommandForLibraryOrdinal:(NSUInteger)ordinal; 88 | 89 | @property (nonatomic, readonly) BOOL hasObjectiveC1Data; 90 | @property (nonatomic, readonly) BOOL hasObjectiveC2Data; 91 | @property (nonatomic, readonly) Class processorClass; 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Source/CDMachOFileDataCursor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDDataCursor.h" 7 | 8 | @class CDMachOFile, CDSection; 9 | 10 | @interface CDMachOFileDataCursor : CDDataCursor 11 | 12 | - (id)initWithFile:(CDMachOFile *)machOFile; 13 | - (id)initWithFile:(CDMachOFile *)machOFile offset:(NSUInteger)offset; 14 | - (id)initWithFile:(CDMachOFile *)machOFile address:(NSUInteger)address; 15 | 16 | - (id)initWithSection:(CDSection *)section; 17 | 18 | @property (nonatomic, weak, readonly) CDMachOFile *machOFile; 19 | 20 | - (void)setAddress:(NSUInteger)address; 21 | 22 | // Read using the current byteOrder 23 | - (uint16_t)readInt16; 24 | - (uint32_t)readInt32; 25 | - (uint64_t)readInt64; 26 | 27 | - (uint32_t)peekInt32; 28 | 29 | // Read using the current byteOrder and ptrSize (from the machOFile) 30 | - (uint64_t)readPtr; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Source/CDMachOFileDataCursor.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDMachOFileDataCursor.h" 7 | 8 | #import "CDMachOFile.h" 9 | #import "CDLCSegment.h" 10 | #import "CDSection.h" 11 | 12 | @implementation CDMachOFileDataCursor 13 | { 14 | __weak CDMachOFile *_machOFile; 15 | NSUInteger _ptrSize; 16 | CDByteOrder _byteOrder; 17 | } 18 | 19 | - (id)initWithFile:(CDMachOFile *)machOFile; 20 | { 21 | return [self initWithFile:machOFile offset:0]; 22 | } 23 | 24 | - (id)initWithFile:(CDMachOFile *)machOFile offset:(NSUInteger)offset; 25 | { 26 | if ((self = [super initWithData:machOFile.data])) { 27 | self.machOFile = machOFile; 28 | [self setOffset:offset]; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | - (id)initWithFile:(CDMachOFile *)machOFile address:(NSUInteger)address; 35 | { 36 | if ((self = [super initWithData:machOFile.data])) { 37 | self.machOFile = machOFile; 38 | [self setAddress:address]; 39 | } 40 | 41 | return self; 42 | } 43 | 44 | - (id)initWithSection:(CDSection *)section; 45 | { 46 | if ((self = [super initWithData:[section data]])) { 47 | self.machOFile = section.segment.machOFile; 48 | } 49 | 50 | return self; 51 | } 52 | 53 | #pragma mark - 54 | 55 | - (void)setMachOFile:(CDMachOFile *)machOFile; 56 | { 57 | _machOFile = machOFile; 58 | _ptrSize = machOFile.ptrSize; 59 | _byteOrder = machOFile.byteOrder; 60 | } 61 | 62 | - (void)setAddress:(NSUInteger)address; 63 | { 64 | NSUInteger dataOffset = [_machOFile dataOffsetForAddress:address]; 65 | [self setOffset:dataOffset]; 66 | } 67 | 68 | #pragma mark - Read using the current byteOrder 69 | 70 | - (uint16_t)readInt16; 71 | { 72 | if (_byteOrder == CDByteOrder_LittleEndian) 73 | return [self readLittleInt16]; 74 | 75 | return [self readBigInt16]; 76 | } 77 | 78 | - (uint32_t)readInt32; 79 | { 80 | if (_byteOrder == CDByteOrder_LittleEndian) 81 | return [self readLittleInt32]; 82 | 83 | return [self readBigInt32]; 84 | } 85 | 86 | - (uint64_t)readInt64; 87 | { 88 | if (_byteOrder == CDByteOrder_LittleEndian) 89 | return [self readLittleInt64]; 90 | 91 | return [self readBigInt64]; 92 | } 93 | 94 | - (uint32_t)peekInt32; 95 | { 96 | NSUInteger savedOffset = self.offset; 97 | uint32_t val = [self readInt32]; 98 | self.offset = savedOffset; 99 | 100 | return val; 101 | } 102 | 103 | - (uint64_t)readPtr; 104 | { 105 | switch (_ptrSize) { 106 | case sizeof(uint32_t): return [self readInt32]; 107 | case sizeof(uint64_t): return [self readInt64]; 108 | } 109 | [NSException raise:NSInternalInconsistencyException format:@"The ptrSize must be either 4 (32-bit) or 8 (64-bit)"]; 110 | return 0; 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /Source/CDMethodType.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType; 7 | 8 | @interface CDMethodType : NSObject 9 | 10 | - (id)initWithType:(CDType *)type offset:(NSString *)offset; 11 | 12 | @property (readonly) CDType *type; 13 | @property (readonly) NSString *offset; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Source/CDMethodType.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDMethodType.h" 7 | 8 | #import "CDType.h" 9 | 10 | @implementation CDMethodType 11 | { 12 | CDType *_type; 13 | NSString *_offset; 14 | } 15 | 16 | - (id)initWithType:(CDType *)type offset:(NSString *)offset; 17 | { 18 | if ((self = [super init])) { 19 | _type = type; 20 | _offset = offset; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | #pragma mark - Debugging 27 | 28 | - (NSString *)description; 29 | { 30 | return [NSString stringWithFormat:@"[%@] type: %@, offset: %@", NSStringFromClass([self class]), self.type, self.offset]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Source/CDMultiFileVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDTextClassDumpVisitor.h" 7 | 8 | #import "CDTypeController.h" // For CDTypeControllerDelegate protocol 9 | 10 | // This generates separate files for each class. Files are created in the 'outputPath' directory. 11 | 12 | @interface CDMultiFileVisitor : CDTextClassDumpVisitor 13 | 14 | @property (strong) NSString *outputPath; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Source/CDOCCategory.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCProtocol.h" 7 | 8 | @class CDOCClassReference; 9 | 10 | @interface CDOCCategory : CDOCProtocol 11 | 12 | @property (strong) CDOCClassReference *classRef; 13 | @property (strong, readonly) NSString *className; 14 | 15 | - (NSString *)methodSearchContext; 16 | - (void)recursivelyVisit:(CDVisitor *)visitor; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Source/CDOCCategory.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCCategory.h" 7 | 8 | #import "CDClassDump.h" 9 | #import "CDOCMethod.h" 10 | #import "CDVisitor.h" 11 | #import "CDVisitorPropertyState.h" 12 | #import "CDOCClass.h" 13 | #import "CDOCClassReference.h" 14 | 15 | @implementation CDOCCategory 16 | 17 | #pragma mark - Superclass overrides 18 | 19 | - (NSString *)sortableName; 20 | { 21 | return [NSString stringWithFormat:@"%@ (%@)", self.className, self.name]; 22 | } 23 | 24 | #pragma mark - 25 | 26 | - (NSString *)className 27 | { 28 | return [_classRef className]; 29 | } 30 | 31 | - (NSString *)methodSearchContext; 32 | { 33 | NSMutableString *resultString = [NSMutableString string]; 34 | 35 | [resultString appendFormat:@"@interface %@ (%@)", self.className, self.name]; 36 | 37 | if ([self.protocols count] > 0) 38 | [resultString appendFormat:@" <%@>", self.protocolsString]; 39 | 40 | return resultString; 41 | } 42 | 43 | - (void)recursivelyVisit:(CDVisitor *)visitor; 44 | { 45 | if ([visitor.classDump shouldShowName:self.name]) { 46 | CDVisitorPropertyState *propertyState = [[CDVisitorPropertyState alloc] initWithProperties:self.properties]; 47 | 48 | [visitor willVisitCategory:self]; 49 | 50 | //[aVisitor willVisitPropertiesOfCategory:self]; 51 | //[self visitProperties:aVisitor]; 52 | //[aVisitor didVisitPropertiesOfCategory:self]; 53 | 54 | [self visitMethods:visitor propertyState:propertyState]; 55 | // This can happen when... the accessors are implemented on the main class. Odd case, but we should still emit the remaining properties. 56 | // Should mostly be dynamic properties 57 | [visitor visitRemainingProperties:propertyState]; 58 | [visitor didVisitCategory:self]; 59 | } 60 | } 61 | 62 | #pragma mark - CDTopologicalSort protocol 63 | 64 | - (NSString *)identifier; 65 | { 66 | return self.sortableName; 67 | } 68 | 69 | - (NSArray *)dependancies; 70 | { 71 | if (self.className == nil) 72 | return @[]; 73 | 74 | return @[self.className]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /Source/CDOCClass.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCProtocol.h" 7 | 8 | #import "CDTopologicalSortProtocol.h" 9 | 10 | @class CDOCClassReference; 11 | 12 | @interface CDOCClass : CDOCProtocol 13 | 14 | @property (strong) CDOCClassReference *superClassRef; 15 | @property (copy, readonly) NSString *superClassName; 16 | @property (strong) NSArray *instanceVariables; 17 | @property (assign) BOOL isExported; 18 | @property (assign) BOOL isSwiftClass; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Source/CDOCClass.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCClass.h" 7 | 8 | #import "CDClassDump.h" 9 | #import "CDOCInstanceVariable.h" 10 | #import "CDOCMethod.h" 11 | #import "CDType.h" 12 | #import "CDTypeController.h" 13 | #import "CDTypeParser.h" 14 | #import "CDVisitor.h" 15 | #import "CDVisitorPropertyState.h" 16 | #import "CDOCClassReference.h" 17 | 18 | @implementation CDOCClass 19 | { 20 | NSArray *_instanceVariables; 21 | 22 | BOOL _isExported; 23 | } 24 | 25 | - (id)init; 26 | { 27 | if ((self = [super init])) { 28 | _isExported = YES; 29 | } 30 | 31 | return self; 32 | } 33 | 34 | #pragma mark - Debugging 35 | 36 | - (NSString *)description; 37 | { 38 | return [NSString stringWithFormat:@"%@, exported: %@", [super description], self.isExported ? @"YES" : @"NO"]; 39 | } 40 | 41 | #pragma mark - 42 | 43 | - (NSString *)superClassName; 44 | { 45 | return [_superClassRef className]; 46 | } 47 | 48 | - (void)registerTypesWithObject:(CDTypeController *)typeController phase:(NSUInteger)phase; 49 | { 50 | [super registerTypesWithObject:typeController phase:phase]; 51 | 52 | for (CDOCInstanceVariable *instanceVariable in self.instanceVariables) { 53 | [instanceVariable.type phase:phase registerTypesWithObject:typeController usedInMethod:NO]; 54 | } 55 | } 56 | 57 | - (NSString *)methodSearchContext; 58 | { 59 | NSMutableString *resultString = [NSMutableString string]; 60 | 61 | [resultString appendFormat:@"@interface %@", self.name]; 62 | if (self.superClassName != nil) 63 | [resultString appendFormat:@" : %@", self.superClassName]; 64 | 65 | if ([self.protocols count] > 0) 66 | [resultString appendFormat:@" <%@>", self.protocolsString]; 67 | 68 | return resultString; 69 | } 70 | 71 | - (void)recursivelyVisit:(CDVisitor *)visitor; 72 | { 73 | if ([visitor.classDump shouldShowName:self.name]) { 74 | CDVisitorPropertyState *propertyState = [[CDVisitorPropertyState alloc] initWithProperties:self.properties]; 75 | 76 | [visitor willVisitClass:self]; 77 | 78 | [visitor willVisitIvarsOfClass:self]; 79 | for (CDOCInstanceVariable *instanceVariable in self.instanceVariables) 80 | [visitor visitIvar:instanceVariable]; 81 | [visitor didVisitIvarsOfClass:self]; 82 | 83 | //[visitor willVisitPropertiesOfClass:self]; 84 | //[self visitProperties:visitor]; 85 | //[visitor didVisitPropertiesOfClass:self]; 86 | 87 | [self visitMethods:visitor propertyState:propertyState]; 88 | // Should mostly be dynamic properties 89 | [visitor visitRemainingProperties:propertyState]; 90 | [visitor didVisitClass:self]; 91 | } 92 | } 93 | 94 | #pragma mark - CDTopologicalSort protocol 95 | 96 | - (NSString *)identifier; 97 | { 98 | return self.name; 99 | } 100 | 101 | - (NSArray *)dependancies; 102 | { 103 | if (self.superClassName == nil) 104 | return @[]; 105 | 106 | return @[self.superClassName]; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /Source/CDOCClassReference.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | @class CDOCClass, CDSymbol; 9 | 10 | /*! 11 | * CDOCClassReference acts as a proxy object to a class that may be external. It can thus be repesented 12 | * as one of: a \c CDOCClass object (for internal classes), a \c CDSymbol object (for external classes), 13 | * or an \c NSString of the class name (for ObjC1 compatibility). The class name can then be inferred from 14 | * any of these representations. 15 | */ 16 | @interface CDOCClassReference : NSObject 17 | 18 | @property (strong) CDOCClass *classObject; 19 | @property (strong) CDSymbol *classSymbol; 20 | @property (nonatomic, copy) NSString *className; // inferred from classObject / classSymbol if not set directly 21 | @property (nonatomic, readonly, getter = isExternalClass) BOOL externalClass; 22 | 23 | - (instancetype)initWithClassObject:(CDOCClass *)classObject; 24 | - (instancetype)initWithClassSymbol:(CDSymbol *)symbol; 25 | - (instancetype)initWithClassName:(NSString *)className; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Source/CDOCClassReference.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCClassReference.h" 7 | #import "CDOCClass.h" 8 | #import "CDSymbol.h" 9 | 10 | @implementation CDOCClassReference 11 | 12 | - (instancetype)initWithClassSymbol:(CDSymbol *)symbol; 13 | { 14 | if ((self = [super init])) { 15 | _classSymbol = symbol; 16 | } 17 | 18 | return self; 19 | } 20 | 21 | - (instancetype)initWithClassObject:(CDOCClass *)classObject; 22 | { 23 | if ((self = [super init])) { 24 | _classObject = classObject; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (instancetype)initWithClassName:(NSString *)className; 31 | { 32 | if ((self = [super init])) { 33 | _className = [className copy]; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | - (NSString *)className; 40 | { 41 | if (_className != nil) 42 | return _className; 43 | else if (_classObject != nil) 44 | return [_classObject name]; 45 | else if (_classSymbol != nil) 46 | return [CDSymbol classNameFromSymbolName:[_classSymbol name]]; 47 | else 48 | return nil; 49 | } 50 | 51 | - (BOOL)isExternalClass; 52 | { 53 | return (!_classObject && (!_classSymbol || [_classSymbol isExternal])); 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Source/CDOCInstanceVariable.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType, CDTypeController; 7 | 8 | @interface CDOCInstanceVariable : NSObject 9 | 10 | - (id)initWithName:(NSString *)name typeString:(NSString *)typeString offset:(NSUInteger)offset; 11 | 12 | @property (readonly) NSString *name; 13 | @property (readonly) NSString *typeString; 14 | @property (readonly) NSUInteger offset; 15 | 16 | // Lazily parses the typeString. Returns nil and sets the parseError if parsing failed. Does not try to parse again in the event of an error. 17 | @property (nonatomic, readonly) CDType *type; 18 | 19 | // This is set after the typeString has been parsed if there was an error. Doesn't trigger parsing. 20 | @property (readonly) NSError *parseError; 21 | 22 | - (void)appendToString:(NSMutableString *)resultString typeController:(CDTypeController *)typeController; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Source/CDOCInstanceVariable.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCInstanceVariable.h" 7 | 8 | #import "CDClassDump.h" 9 | #import "CDTypeFormatter.h" 10 | #import "CDTypeParser.h" 11 | #import "CDTypeController.h" 12 | #import "CDType.h" 13 | 14 | @interface CDOCInstanceVariable () 15 | @property (assign) BOOL hasParsedType; 16 | @end 17 | 18 | #pragma mark - 19 | 20 | @implementation CDOCInstanceVariable 21 | { 22 | NSString *_name; 23 | NSString *_typeString; 24 | NSUInteger _offset; 25 | 26 | BOOL _hasParsedType; 27 | CDType *_type; 28 | NSError *_parseError; 29 | } 30 | 31 | - (id)initWithName:(NSString *)name typeString:(NSString *)typeString offset:(NSUInteger)offset; 32 | { 33 | if ((self = [super init])) { 34 | _name = name; 35 | _typeString = typeString; 36 | _offset = offset; 37 | 38 | _hasParsedType = NO; 39 | _type = nil; 40 | _parseError = nil; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | #pragma mark - Debugging 47 | 48 | - (NSString *)description; 49 | { 50 | return [NSString stringWithFormat:@"[%@] name: %@, typeString: '%@', offset: %lu", 51 | NSStringFromClass([self class]), self.name, self.typeString, self.offset]; 52 | } 53 | 54 | #pragma mark - 55 | 56 | - (CDType *)type; 57 | { 58 | if (self.hasParsedType == NO && self.parseError == nil) { 59 | CDTypeParser *parser = [[CDTypeParser alloc] initWithString:self.typeString]; 60 | NSError *error; 61 | _type = [parser parseType:&error]; 62 | if (_type == nil) { 63 | NSLog(@"Warning: Parsing instance variable type failed, %@", self.name); 64 | _parseError = error; 65 | } else { 66 | self.hasParsedType = YES; 67 | } 68 | } 69 | 70 | return _type; 71 | } 72 | 73 | - (void)appendToString:(NSMutableString *)resultString typeController:(CDTypeController *)typeController; 74 | { 75 | CDType *type = [self type]; // Parses it, if necessary; 76 | if (self.parseError != nil) { 77 | if ([self.typeString length] > 0) { 78 | [resultString appendFormat:@" // Error: parsing type: '%@', name: %@", self.typeString, self.name]; 79 | } else { 80 | [resultString appendFormat:@" // Error: Empty type, name: %@", self.name]; 81 | } 82 | } else { 83 | NSString *formattedString = [[typeController ivarTypeFormatter] formatVariable:self.name type:type]; 84 | NSParameterAssert(formattedString != nil); 85 | [resultString appendString:formattedString]; 86 | [resultString appendString:@";"]; 87 | if ([typeController shouldShowIvarOffsets]) { 88 | [resultString appendFormat:@"\t// %ld = 0x%lx", self.offset, self.offset]; 89 | } 90 | } 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Source/CDOCMethod.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDTypeController; 7 | 8 | @interface CDOCMethod : NSObject 9 | 10 | - (id)initWithName:(NSString *)name typeString:(NSString *)typeString; 11 | - (id)initWithName:(NSString *)name typeString:(NSString *)typeString address:(NSUInteger)address; 12 | 13 | @property (readonly) NSString *name; 14 | @property (readonly) NSString *typeString; 15 | @property (assign) NSUInteger address; 16 | 17 | - (NSArray *)parsedMethodTypes; 18 | 19 | - (void)appendToString:(NSMutableString *)resultString typeController:(CDTypeController *)typeController; 20 | 21 | - (NSComparisonResult)ascendingCompareByName:(CDOCMethod *)other; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Source/CDOCMethod.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCMethod.h" 7 | 8 | #import "CDClassDump.h" 9 | #import "CDTypeFormatter.h" 10 | #import "CDTypeParser.h" 11 | #import "CDTypeController.h" 12 | 13 | @implementation CDOCMethod 14 | { 15 | NSString *_name; 16 | NSString *_typeString; 17 | NSUInteger _address; 18 | 19 | BOOL _hasParsedType; 20 | NSArray *_parsedMethodTypes; 21 | } 22 | 23 | - (id)init; 24 | { 25 | [NSException raise:@"RejectUnusedImplementation" format:@"-initWithName:typeString:imp: is the designated initializer"]; 26 | return nil; 27 | } 28 | 29 | - (id)initWithName:(NSString *)name typeString:(NSString *)typeString; 30 | { 31 | return [self initWithName:name typeString:typeString address:0]; 32 | } 33 | 34 | - (id)initWithName:(NSString *)name typeString:(NSString *)typeString address:(NSUInteger)address; 35 | { 36 | if ((self = [super init])) { 37 | _name = name; 38 | _typeString = typeString; 39 | _address = address; 40 | 41 | _hasParsedType = NO; 42 | _parsedMethodTypes = nil; 43 | } 44 | 45 | return self; 46 | } 47 | 48 | #pragma mark - NSCopying 49 | 50 | - (id)copyWithZone:(NSZone *)zone; 51 | { 52 | return [[CDOCMethod alloc] initWithName:self.name typeString:self.typeString address:self.address]; 53 | } 54 | 55 | #pragma mark - Debugging 56 | 57 | - (NSString *)description; 58 | { 59 | return [NSString stringWithFormat:@"[%@] name: %@, typeString: %@, address: 0x%016lx", 60 | NSStringFromClass([self class]), self.name, self.typeString, self.address]; 61 | } 62 | 63 | #pragma mark - 64 | 65 | - (NSArray *)parsedMethodTypes; 66 | { 67 | if (_hasParsedType == NO) { 68 | NSError *error = nil; 69 | 70 | CDTypeParser *parser = [[CDTypeParser alloc] initWithString:self.typeString]; 71 | _parsedMethodTypes = [parser parseMethodType:&error]; 72 | if (_parsedMethodTypes == nil) 73 | NSLog(@"Warning: Parsing method types failed, %@", self.name); 74 | _hasParsedType = YES; 75 | } 76 | 77 | return _parsedMethodTypes; 78 | } 79 | 80 | - (void)appendToString:(NSMutableString *)resultString typeController:(CDTypeController *)typeController; 81 | { 82 | NSString *formattedString = [typeController.methodTypeFormatter formatMethodName:self.name typeString:self.typeString]; 83 | if (formattedString != nil) { 84 | [resultString appendString:formattedString]; 85 | [resultString appendString:@";"]; 86 | if (typeController.shouldShowMethodAddresses && self.address != 0) { 87 | if (typeController.targetArchUses64BitABI) 88 | [resultString appendFormat:@"\t// IMP=0x%016lx", self.address]; 89 | else 90 | [resultString appendFormat:@"\t// IMP=0x%08lx", self.address]; 91 | } 92 | } else 93 | [resultString appendFormat:@" // Error parsing type: %@, name: %@", self.typeString, self.name]; 94 | } 95 | 96 | #pragma mark - Sorting 97 | 98 | - (NSComparisonResult)ascendingCompareByName:(CDOCMethod *)other; 99 | { 100 | return [self.name compare:other.name]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /Source/CDOCModule.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDOCSymtab; 7 | 8 | @interface CDOCModule : NSObject 9 | 10 | @property (assign) uint32_t version; 11 | @property (strong) NSString *name; 12 | @property (strong) CDOCSymtab *symtab; 13 | 14 | - (NSString *)formattedString; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Source/CDOCModule.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCModule.h" 7 | 8 | #import "CDObjectiveC1Processor.h" 9 | #import "CDOCSymtab.h" 10 | 11 | @implementation CDOCModule 12 | { 13 | uint32_t _version; 14 | NSString *_name; 15 | CDOCSymtab *_symtab; 16 | } 17 | 18 | - (id)init; 19 | { 20 | if ((self = [super init])) { 21 | _version = 0; 22 | _name = nil; 23 | _symtab = nil; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | #pragma mark - Debugging 30 | 31 | - (NSString *)description; 32 | { 33 | return [NSString stringWithFormat:@"[%@] name: %@, version: %u, symtab: %@", NSStringFromClass([self class]), self.name, self.version, self.symtab]; 34 | } 35 | 36 | #pragma mark - 37 | 38 | - (NSString *)formattedString; 39 | { 40 | return [NSString stringWithFormat:@"//\n// %@\n//\n", self.name]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Source/CDOCProperty.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType; 7 | 8 | @interface CDOCProperty : NSObject 9 | 10 | - (id)initWithName:(NSString *)name attributes:(NSString *)attributes; 11 | 12 | @property (readonly) NSString *name; 13 | @property (readonly) NSString *attributeString; 14 | @property (readonly) CDType *type; 15 | @property (readonly) NSArray *attributes; 16 | 17 | @property (strong) NSString *attributeStringAfterType; 18 | 19 | @property (nonatomic, readonly) NSString *defaultGetter; 20 | @property (nonatomic, readonly) NSString *defaultSetter; 21 | 22 | @property (strong) NSString *customGetter; 23 | @property (strong) NSString *customSetter; 24 | 25 | @property (nonatomic, readonly) NSString *getter; 26 | @property (nonatomic, readonly) NSString *setter; 27 | 28 | @property (readonly) BOOL isReadOnly; 29 | @property (readonly) BOOL isDynamic; 30 | 31 | - (NSComparisonResult)ascendingCompareByName:(CDOCProperty *)other; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Source/CDOCProtocol.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDTypeController; 7 | @class CDVisitor, CDVisitorPropertyState; 8 | @class CDOCMethod, CDOCProperty; 9 | 10 | @interface CDOCProtocol : NSObject 11 | 12 | @property (strong) NSString *name; 13 | 14 | @property (readonly) NSArray *protocols; 15 | - (void)addProtocol:(CDOCProtocol *)protocol; 16 | - (void)removeProtocol:(CDOCProtocol *)protocol; 17 | @property (nonatomic, readonly) NSArray *protocolNames; 18 | @property (nonatomic, readonly) NSString *protocolsString; 19 | 20 | @property (nonatomic, readonly) NSArray *classMethods; // TODO: NSArray vs. NSMutableArray 21 | - (void)addClassMethod:(CDOCMethod *)method; 22 | 23 | @property (nonatomic, readonly) NSArray *instanceMethods; 24 | - (void)addInstanceMethod:(CDOCMethod *)method; 25 | 26 | @property (nonatomic, readonly) NSArray *optionalClassMethods; 27 | - (void)addOptionalClassMethod:(CDOCMethod *)method; 28 | 29 | @property (nonatomic, readonly) NSArray *optionalInstanceMethods; 30 | - (void)addOptionalInstanceMethod:(CDOCMethod *)method; 31 | 32 | @property (nonatomic, readonly) NSArray *properties; 33 | - (void)addProperty:(CDOCProperty *)property; 34 | 35 | @property (nonatomic, readonly) BOOL hasMethods; 36 | 37 | - (void)registerTypesWithObject:(CDTypeController *)typeController phase:(NSUInteger)phase; 38 | - (void)registerTypesFromMethods:(NSArray *)methods withObject:(CDTypeController *)typeController phase:(NSUInteger)phase; 39 | 40 | - (NSComparisonResult)ascendingCompareByName:(CDOCProtocol *)other; 41 | 42 | - (NSString *)methodSearchContext; 43 | - (void)recursivelyVisit:(CDVisitor *)visitor; 44 | 45 | - (void)visitMethods:(CDVisitor *)visitor propertyState:(CDVisitorPropertyState *)propertyState; 46 | 47 | - (void)mergeMethodsFromProtocol:(CDOCProtocol *)other; 48 | - (void)mergePropertiesFromProtocol:(CDOCProtocol *)other; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Source/CDOCSymtab.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDOCCategory, CDOCClass; 7 | 8 | @interface CDOCSymtab : NSObject 9 | 10 | @property (readonly) NSMutableArray *classes; 11 | - (void)addClass:(CDOCClass *)aClass; 12 | 13 | @property (readonly) NSMutableArray *categories; 14 | - (void)addCategory:(CDOCCategory *)category; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Source/CDOCSymtab.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDOCSymtab.h" 7 | 8 | #import "CDOCCategory.h" 9 | #import "CDOCClass.h" 10 | 11 | @implementation CDOCSymtab 12 | { 13 | NSMutableArray *_classes; 14 | NSMutableArray *_categories; 15 | } 16 | 17 | - (id)init; 18 | { 19 | if ((self = [super init])) { 20 | _classes = [[NSMutableArray alloc] init]; 21 | _categories = [[NSMutableArray alloc] init]; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | #pragma mark - Debugging 28 | 29 | - (NSString *)description; 30 | { 31 | return [NSString stringWithFormat:@"[%@] classes: %@, categories: %@", NSStringFromClass([self class]), self.classes, self.categories]; 32 | } 33 | 34 | #pragma mark - 35 | 36 | - (void)addClass:(CDOCClass *)aClass; 37 | { 38 | [self.classes addObject:aClass]; 39 | } 40 | 41 | - (void)addCategory:(CDOCCategory *)category; 42 | { 43 | [self.categories addObject:category]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Source/CDObjectiveC1Processor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDObjectiveCProcessor.h" 7 | 8 | @interface CDObjectiveC1Processor : CDObjectiveCProcessor 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDObjectiveC2Processor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDObjectiveCProcessor.h" 7 | 8 | @interface CDObjectiveC2Processor : CDObjectiveCProcessor 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDObjectiveCProcessor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDMachOFile, CDSection, CDTypeController; 7 | @class CDVisitor; 8 | @class CDOCClass, CDOCCategory; 9 | @class CDProtocolUniquer; 10 | 11 | @interface CDObjectiveCProcessor : NSObject 12 | 13 | - (id)initWithMachOFile:(CDMachOFile *)machOFile; 14 | 15 | @property (readonly) CDMachOFile *machOFile; 16 | @property (nonatomic, readonly) BOOL hasObjectiveCData; 17 | 18 | @property (nonatomic, readonly) CDSection *objcImageInfoSection; 19 | @property (nonatomic, readonly) NSString *garbageCollectionStatus; 20 | 21 | - (void)addClass:(CDOCClass *)aClass withAddress:(uint64_t)address; 22 | - (CDOCClass *)classWithAddress:(uint64_t)address; 23 | 24 | - (void)addClassesFromArray:(NSArray *)array; 25 | - (void)addCategoriesFromArray:(NSArray *)array; 26 | 27 | - (void)addCategory:(CDOCCategory *)category; 28 | 29 | - (void)process; 30 | - (void)loadProtocols; 31 | - (void)loadClasses; 32 | - (void)loadCategories; 33 | 34 | - (void)registerTypesWithObject:(CDTypeController *)typeController phase:(NSUInteger)phase; 35 | - (void)recursivelyVisit:(CDVisitor *)visitor; 36 | 37 | - (NSArray *)protocolAddressListAtAddress:(uint64_t)address; 38 | 39 | @property (readonly) CDProtocolUniquer *protocolUniquer; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Source/CDProtocolUniquer.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDOCProtocol; 7 | 8 | @interface CDProtocolUniquer : NSObject 9 | 10 | // Gather 11 | - (CDOCProtocol *)protocolWithAddress:(uint64_t)address; 12 | - (void)setProtocol:(CDOCProtocol *)protocol withAddress:(uint64_t)address; 13 | 14 | // Process 15 | - (void)createUniquedProtocols; 16 | 17 | // Results 18 | - (NSArray *)uniqueProtocolsAtAddresses:(NSArray *)addresses; 19 | - (NSArray *)uniqueProtocolsSortedByName; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Source/CDRelocationInfo.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #include 7 | 8 | typedef enum : NSUInteger { 9 | CDRelocationInfoSize_8Bit = 0, 10 | CDRelocationInfoSize_16Bit = 1, 11 | CDRelocationInfoSize_32Bit = 2, 12 | CDRelocationInfoSize_64Bit = 3, 13 | } CDRelocationSize; 14 | 15 | @interface CDRelocationInfo : NSObject 16 | 17 | - (id)initWithInfo:(struct relocation_info)info; 18 | 19 | @property (nonatomic, readonly) NSUInteger offset; 20 | @property (nonatomic, readonly) CDRelocationSize size; 21 | @property (nonatomic, readonly) uint32_t symbolnum; 22 | @property (nonatomic, readonly) BOOL isExtern; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Source/CDRelocationInfo.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDRelocationInfo.h" 7 | 8 | @implementation CDRelocationInfo 9 | { 10 | struct relocation_info _rinfo; 11 | } 12 | 13 | - (id)initWithInfo:(struct relocation_info)info; 14 | { 15 | if ((self = [super init])) { 16 | _rinfo = info; 17 | } 18 | 19 | return self; 20 | } 21 | 22 | #pragma mark - Debugging 23 | 24 | - (NSString *)description; 25 | { 26 | return [NSString stringWithFormat:@"<%@:%p> addr/off: %08x, sym #: %5u, pcrel? %u, len: %u, extern? %u, type: %x", 27 | NSStringFromClass([self class]), self, 28 | _rinfo.r_address, _rinfo.r_symbolnum, _rinfo.r_pcrel, _rinfo.r_length, _rinfo.r_extern, _rinfo.r_type]; 29 | } 30 | 31 | #pragma mark - 32 | 33 | - (NSUInteger)offset; 34 | { 35 | return _rinfo.r_address; 36 | } 37 | 38 | - (CDRelocationSize)size; 39 | { 40 | return _rinfo.r_length; 41 | } 42 | 43 | - (uint32_t)symbolnum; 44 | { 45 | return _rinfo.r_symbolnum; 46 | } 47 | 48 | - (BOOL)isExtern; 49 | { 50 | return _rinfo.r_extern == 1; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Source/CDSearchPathState.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface CDSearchPathState : NSObject 7 | 8 | @property (nonatomic, strong) NSString *executablePath; 9 | 10 | - (void)pushSearchPaths:(NSArray *)searchPaths; 11 | - (void)popSearchPaths; 12 | 13 | - (NSArray *)searchPaths; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Source/CDSearchPathState.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDSearchPathState.h" 7 | 8 | @interface CDSearchPathState () 9 | @property (readonly) NSMutableArray *searchPathStack; 10 | @end 11 | 12 | #pragma mark - 13 | 14 | @implementation CDSearchPathState 15 | { 16 | NSString *_executablePath; 17 | NSMutableArray *_searchPathStack; 18 | } 19 | 20 | - (id)init; 21 | { 22 | if ((self = [super init])) { 23 | _executablePath = nil; 24 | _searchPathStack = [[NSMutableArray alloc] init]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | #pragma mark - 31 | 32 | - (void)pushSearchPaths:(NSArray *)searchPaths; 33 | { 34 | [self.searchPathStack addObject:searchPaths]; 35 | } 36 | 37 | - (void)popSearchPaths; 38 | { 39 | if ([self.searchPathStack count] > 0) { 40 | [self.searchPathStack removeLastObject]; 41 | } else { 42 | NSLog(@"Warning: Unbalanced popSearchPaths"); 43 | } 44 | } 45 | 46 | - (NSArray *)searchPaths; 47 | { 48 | NSMutableArray *result = [NSMutableArray array]; 49 | for (NSArray *group in self.searchPathStack) { 50 | [result addObjectsFromArray:group]; 51 | } 52 | 53 | return [result copy]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Source/CDSection.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDMachOFileDataCursor; 7 | @class CDLCSegment; 8 | 9 | @interface CDSection : NSObject 10 | 11 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment *)segment; 12 | 13 | @property (weak, readonly) CDLCSegment *segment; 14 | 15 | @property (nonatomic, readonly) NSData *data; 16 | 17 | @property (nonatomic, readonly) NSString *segmentName; 18 | @property (nonatomic, readonly) NSString *sectionName; 19 | 20 | @property (nonatomic, readonly) NSUInteger addr; 21 | @property (nonatomic, readonly) NSUInteger size; 22 | 23 | - (BOOL)containsAddress:(NSUInteger)address; 24 | - (NSUInteger)fileOffsetForAddress:(NSUInteger)address; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Source/CDSection.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDSection.h" 7 | 8 | #include 9 | #import "CDMachOFile.h" 10 | #import "CDMachOFileDataCursor.h" 11 | #import "CDLCSegment.h" 12 | 13 | @implementation CDSection 14 | { 15 | struct section_64 _section; // 64-bit, also holding 32-bit 16 | } 17 | 18 | @synthesize data = _data; 19 | 20 | - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment *)segment; 21 | { 22 | if ((self = [super init])) { 23 | _segment = segment; 24 | 25 | _sectionName = [cursor readStringOfLength:16 encoding:NSASCIIStringEncoding]; 26 | size_t sectionNameLength = [_sectionName lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 27 | memcpy(_section.sectname, [_sectionName UTF8String], MIN(sectionNameLength, sizeof(_section.sectname))); 28 | size_t segmentNameLength = [_sectionName lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; 29 | _segmentName = [cursor readStringOfLength:16 encoding:NSASCIIStringEncoding]; 30 | memcpy(_section.segname, [_segmentName UTF8String], MIN(segmentNameLength, sizeof(_section.segname))); 31 | _section.addr = [cursor readPtr]; 32 | _section.size = [cursor readPtr]; 33 | _section.offset = [cursor readInt32]; 34 | uint32_t dyldOffset = (uint32_t)(_section.addr - segment.vmaddr + segment.fileoff); 35 | if (_section.offset > 0 && _section.offset != dyldOffset) { 36 | fprintf(stderr, "Warning: Invalid section offset 0x%08x replaced with 0x%08x in %s,%s\n", _section.offset, dyldOffset, [_segmentName UTF8String], [_sectionName UTF8String]); 37 | _section.offset = dyldOffset; 38 | } 39 | _section.align = [cursor readInt32]; 40 | _section.reloff = [cursor readInt32]; 41 | _section.nreloc = [cursor readInt32]; 42 | _section.flags = [cursor readInt32]; 43 | _section.reserved1 = [cursor readInt32]; 44 | _section.reserved2 = [cursor readInt32]; 45 | if (cursor.machOFile.uses64BitABI) { 46 | _section.reserved3 = [cursor readInt32]; 47 | } 48 | } 49 | 50 | return self; 51 | } 52 | 53 | #pragma mark - 54 | 55 | - (NSData *)data; 56 | { 57 | if (!_data) { 58 | _data = [[NSData alloc] initWithBytes:(uint8_t *)[self.segment.machOFile.data bytes] + _section.offset length:_section.size]; 59 | } 60 | return _data; 61 | } 62 | 63 | - (NSUInteger)addr; 64 | { 65 | return _section.addr; 66 | } 67 | 68 | - (NSUInteger)size; 69 | { 70 | return _section.size; 71 | } 72 | 73 | - (BOOL)containsAddress:(NSUInteger)address; 74 | { 75 | return (address >= _section.addr) && (address < _section.addr + _section.size); 76 | } 77 | 78 | - (NSUInteger)fileOffsetForAddress:(NSUInteger)address; 79 | { 80 | NSParameterAssert([self containsAddress:address]); 81 | return _section.offset + address - _section.addr; 82 | } 83 | 84 | #pragma mark - Debugging 85 | 86 | - (NSString *)description; 87 | { 88 | int padding = (int)self.segment.machOFile.ptrSize * 2; 89 | return [NSString stringWithFormat:@"<%@:%p> '%@,%-16s' addr: %0*llx, size: %0*llx", 90 | NSStringFromClass([self class]), self, 91 | self.segmentName, [self.sectionName UTF8String], 92 | padding, _section.addr, padding, _section.size]; 93 | } 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /Source/CDStructureInfo.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType; 7 | 8 | @interface CDStructureInfo : NSObject 9 | 10 | - (id)initWithType:(CDType *)type; 11 | 12 | - (NSString *)shortDescription; 13 | 14 | @property (readonly) CDType *type; 15 | 16 | @property (assign) NSUInteger referenceCount; 17 | - (void)addReferenceCount:(NSUInteger)count; 18 | 19 | @property (assign) BOOL isUsedInMethod; 20 | @property (strong) NSString *typedefName; 21 | 22 | - (void)generateTypedefName:(NSString *)baseName; 23 | 24 | @property (nonatomic, readonly) NSString *name; 25 | 26 | - (NSComparisonResult)ascendingCompareByStructureDepth:(CDStructureInfo *)other; 27 | - (NSComparisonResult)descendingCompareByStructureDepth:(CDStructureInfo *)other; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Source/CDStructureTable.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType, CDTypeController, CDTypeFormatter; 7 | 8 | @interface CDStructureTable : NSObject 9 | 10 | @property (strong) NSString *identifier; 11 | @property (strong) NSString *anonymousBaseName; 12 | @property (assign) BOOL shouldDebug; 13 | 14 | @property (weak) CDTypeController *typeController; 15 | 16 | // Phase 0 17 | - (void)phase0RegisterStructure:(CDType *)structure usedInMethod:(BOOL)isUsedInMethod; 18 | - (void)finishPhase0; 19 | 20 | // Phase 1 21 | - (void)runPhase1; 22 | - (void)phase1RegisterStructure:(CDType *)structure; 23 | - (void)finishPhase1; 24 | @property (nonatomic, readonly) NSUInteger phase1_maxDepth; 25 | 26 | // Phase 2 27 | - (void)runPhase2AtDepth:(NSUInteger)depth; 28 | - (CDType *)phase2ReplacementForType:(CDType *)type; 29 | 30 | - (void)finishPhase2; 31 | 32 | // Phase 3 33 | - (void)phase2ReplacementOnPhase0; 34 | 35 | - (void)buildPhase3Exceptions; 36 | - (void)runPhase3; 37 | - (void)phase3RegisterStructure:(CDType *)structure 38 | count:(NSUInteger)referenceCount 39 | usedInMethod:(BOOL)isUsedInMethod; 40 | - (void)finishPhase3; 41 | - (CDType *)phase3ReplacementForType:(CDType *)type; 42 | 43 | // Other 44 | 45 | // Called by CDTypeController prior to calling the next two methods. 46 | - (void)generateTypedefNames; 47 | - (void)generateMemberNames; 48 | 49 | // Called by CDTypeController 50 | - (void)appendNamedStructuresToString:(NSMutableString *)resultString 51 | formatter:(CDTypeFormatter *)typeFormatter 52 | markName:(NSString *)markName; 53 | 54 | // Called by CDTypeController 55 | - (void)appendTypedefsToString:(NSMutableString *)resultString 56 | formatter:(CDTypeFormatter *)typeFormatter 57 | markName:(NSString *)markName; 58 | 59 | - (BOOL)shouldExpandType:(CDType *)type; 60 | - (NSString *)typedefNameForType:(CDType *)type; 61 | 62 | // Debugging 63 | - (void)debugName:(NSString *)name; 64 | - (void)debugAnon:(NSString *)str; 65 | - (void)logPhase0Info; 66 | - (void)logPhase2Info; 67 | - (void)logPhase3Info; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Source/CDSymbol.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #include 7 | 8 | extern NSString *const ObjCClassSymbolPrefix; 9 | 10 | @class CDMachOFile, CDSection, CDLCDylib; 11 | 12 | @interface CDSymbol : NSObject 13 | 14 | - (id)initWithName:(NSString *)name machOFile:(CDMachOFile *)machOFile nlist32:(struct nlist)nlist32; 15 | - (id)initWithName:(NSString *)name machOFile:(CDMachOFile *)machOFile nlist64:(struct nlist_64)nlist64; 16 | 17 | @property (nonatomic, readonly) uint64_t value; 18 | @property (readonly) NSString *name; 19 | @property (nonatomic, readonly) CDSection *section; 20 | @property (nonatomic, readonly) CDLCDylib *dylibLoadCommand; 21 | 22 | @property (nonatomic, readonly) BOOL isExternal; 23 | @property (nonatomic, readonly) BOOL isPrivateExternal; 24 | @property (nonatomic, readonly) NSUInteger stab; 25 | @property (nonatomic, readonly) NSUInteger type; 26 | @property (nonatomic, readonly) BOOL isDefined; 27 | @property (nonatomic, readonly) BOOL isAbsolute; 28 | @property (nonatomic, readonly) BOOL isInSection; 29 | @property (nonatomic, readonly) BOOL isPrebound; 30 | @property (nonatomic, readonly) BOOL isIndirect; 31 | @property (nonatomic, readonly) BOOL isCommon; 32 | @property (nonatomic, readonly) BOOL isInTextSection; 33 | @property (nonatomic, readonly) BOOL isInDataSection; 34 | @property (nonatomic, readonly) BOOL isInBssSection; 35 | @property (nonatomic, readonly) NSUInteger referenceType; 36 | @property (nonatomic, readonly) NSString *referenceTypeName; 37 | @property (nonatomic, readonly) NSString *shortTypeDescription; 38 | @property (nonatomic, readonly) NSString *longTypeDescription; 39 | 40 | - (NSComparisonResult)compare:(CDSymbol *)other; 41 | - (NSComparisonResult)compareByName:(CDSymbol *)other; 42 | 43 | + (NSString *)classNameFromSymbolName:(NSString *)symbolName; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Source/CDTextClassDumpVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDVisitor.h" 7 | 8 | // Has a mutable string for storing output, and method to write it to standard out. 9 | // symbol references are for... ? 10 | 11 | @interface CDTextClassDumpVisitor : CDVisitor 12 | 13 | @property (readonly) NSMutableString *resultString; 14 | 15 | - (void)writeResultToStandardOutput; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Source/CDTopoSortNode.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDTopologicalSortProtocol.h" 7 | 8 | typedef enum : NSUInteger { 9 | CDNodeColor_White = 0, 10 | CDNodeColor_Gray = 1, 11 | CDNodeColor_Black = 2, 12 | } CDNodeColor; 13 | 14 | @interface CDTopoSortNode : NSObject 15 | 16 | - (id)initWithObject:(id )object; 17 | 18 | @property (nonatomic, readonly) NSString *identifier; 19 | @property (readonly) id sortableObject; 20 | 21 | - (NSArray *)dependancies; 22 | - (void)addDependancy:(NSString *)identifier; 23 | - (void)removeDependancy:(NSString *)identifier; 24 | - (void)addDependanciesFromArray:(NSArray *)identifiers; 25 | @property (nonatomic, readonly) NSString *dependancyDescription; 26 | 27 | @property (assign) CDNodeColor color; 28 | 29 | - (NSComparisonResult)ascendingCompareByIdentifier:(CDTopoSortNode *)other; 30 | - (void)topologicallySortNodes:(NSDictionary *)nodesByIdentifier intoArray:(NSMutableArray *)sortedArray; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Source/CDTopoSortNode.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDTopoSortNode.h" 7 | 8 | @implementation CDTopoSortNode 9 | { 10 | id _sortableObject; 11 | 12 | NSMutableSet *_dependancies; 13 | CDNodeColor _color; 14 | } 15 | 16 | - (id)initWithObject:(id )object; 17 | { 18 | if ((self = [super init])) { 19 | _sortableObject = object; 20 | _dependancies = [[NSMutableSet alloc] init]; 21 | _color = CDNodeColor_White; 22 | 23 | [self addDependanciesFromArray:[_sortableObject dependancies]]; 24 | } 25 | 26 | return self; 27 | } 28 | 29 | #pragma mark - Debugging 30 | 31 | - (NSString *)description; 32 | { 33 | return [NSString stringWithFormat:@"%@ (%lu) depends on %@", self.identifier, self.color, self.dependancyDescription]; 34 | } 35 | 36 | #pragma mark - 37 | 38 | - (NSString *)identifier; 39 | { 40 | return self.sortableObject.identifier; 41 | } 42 | 43 | - (NSArray *)dependancies; 44 | { 45 | return [_dependancies allObjects]; 46 | } 47 | 48 | - (void)addDependancy:(NSString *)identifier; 49 | { 50 | [_dependancies addObject:identifier]; 51 | } 52 | 53 | - (void)removeDependancy:(NSString *)identifier; 54 | { 55 | [_dependancies removeObject:identifier]; 56 | } 57 | 58 | - (void)addDependanciesFromArray:(NSArray *)identifiers; 59 | { 60 | [_dependancies addObjectsFromArray:identifiers]; 61 | } 62 | 63 | - (NSString *)dependancyDescription; 64 | { 65 | return [[_dependancies allObjects] componentsJoinedByString:@", "]; 66 | } 67 | 68 | #pragma mark - Sorting 69 | 70 | - (NSComparisonResult)ascendingCompareByIdentifier:(CDTopoSortNode *)other; 71 | { 72 | return [self.identifier compare:other.identifier]; 73 | } 74 | 75 | - (void)topologicallySortNodes:(NSDictionary *)nodesByIdentifier intoArray:(NSMutableArray *)sortedArray; 76 | { 77 | NSArray *dependantIdentifiers = [self dependancies]; 78 | 79 | for (NSString *identifier in dependantIdentifiers) { 80 | CDTopoSortNode *node = nodesByIdentifier[identifier]; 81 | if (node.color == CDNodeColor_White) { 82 | node.color = CDNodeColor_Gray; 83 | [node topologicallySortNodes:nodesByIdentifier intoArray:sortedArray]; 84 | } else if (node.color == CDNodeColor_Gray) { 85 | NSLog(@"Warning: Possible circular reference? %@ -> %@", self.identifier, node.identifier); 86 | } 87 | } 88 | 89 | [sortedArray addObject:[self sortableObject]]; 90 | self.color = CDNodeColor_Black; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Source/CDTopologicalSortProtocol.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | // A rather clunky way to avoid warnings in CDTopoSortNode.m regarding -retain not implemented by protocols 7 | @protocol CDTopologicalSort 8 | @property (nonatomic, readonly) NSString *identifier; 9 | @property (nonatomic, readonly) NSArray *dependancies; 10 | @end 11 | -------------------------------------------------------------------------------- /Source/CDType.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDTypeController, CDTypeFormatter, CDTypeName; 7 | 8 | @interface CDType : NSObject 9 | 10 | - (id)initSimpleType:(int)type; 11 | - (id)initIDType:(CDTypeName *)name; 12 | - (id)initIDType:(CDTypeName *)name withProtocols:(NSArray *)protocols; 13 | - (id)initIDTypeWithProtocols:(NSArray *)protocols; 14 | - (id)initStructType:(CDTypeName *)name members:(NSArray *)members; 15 | - (id)initUnionType:(CDTypeName *)name members:(NSArray *)members; 16 | - (id)initBitfieldType:(NSString *)bitfieldSize; 17 | - (id)initArrayType:(CDType *)type count:(NSString *)count; 18 | - (id)initPointerType:(CDType *)type; 19 | - (id)initFunctionPointerType; 20 | - (id)initBlockTypeWithTypes:(NSArray *)types; 21 | - (id)initModifier:(int)modifier type:(CDType *)type; 22 | 23 | @property (strong) NSString *variableName; 24 | 25 | @property (nonatomic, readonly) int primitiveType; 26 | @property (nonatomic, readonly) BOOL isIDType; 27 | @property (nonatomic, readonly) BOOL isNamedObject; 28 | @property (nonatomic, readonly) BOOL isTemplateType; 29 | 30 | @property (nonatomic, readonly) CDType *subtype; 31 | @property (nonatomic, readonly) CDTypeName *typeName; 32 | 33 | @property (nonatomic, readonly) NSArray *members; 34 | @property (nonatomic, readonly) NSArray *types; 35 | 36 | @property (nonatomic, readonly) int typeIgnoringModifiers; 37 | @property (nonatomic, readonly) NSUInteger structureDepth; 38 | 39 | - (NSString *)formattedString:(NSString *)previousName formatter:(CDTypeFormatter *)typeFormatter level:(NSUInteger)level; 40 | 41 | @property (nonatomic, readonly) NSString *typeString; 42 | @property (nonatomic, readonly) NSString *bareTypeString; 43 | @property (nonatomic, readonly) NSString *reallyBareTypeString; 44 | @property (nonatomic, readonly) NSString *keyTypeString; 45 | 46 | 47 | - (BOOL)canMergeWithType:(CDType *)otherType; 48 | - (void)mergeWithType:(CDType *)otherType; 49 | 50 | @property (nonatomic, readonly) NSArray *memberVariableNames; 51 | - (void)generateMemberNames; 52 | 53 | // Phase 0 54 | - (void)phase:(NSUInteger)phase registerTypesWithObject:(CDTypeController *)typeController usedInMethod:(BOOL)isUsedInMethod; 55 | - (void)phase0RecursivelyFixStructureNames:(BOOL)flag; 56 | 57 | // Phase 1 58 | - (void)phase1RegisterStructuresWithObject:(CDTypeController *)typeController; 59 | 60 | // Phase 2 61 | - (void)phase2MergeWithTypeController:(CDTypeController *)typeController debug:(BOOL)phase2Debug; 62 | 63 | // Phase 3 64 | - (void)phase3RegisterMembersWithTypeController:(CDTypeController *)typeController; 65 | - (void)phase3MergeWithTypeController:(CDTypeController *)typeController; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Source/CDTypeController.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @protocol CDTypeControllerDelegate; 7 | 8 | @class CDClassDump, CDType, CDTypeFormatter; 9 | 10 | @interface CDTypeController : NSObject 11 | 12 | - (id)initWithClassDump:(CDClassDump *)classDump; 13 | 14 | @property (weak) id delegate; 15 | 16 | @property (readonly) CDTypeFormatter *ivarTypeFormatter; 17 | @property (readonly) CDTypeFormatter *methodTypeFormatter; 18 | @property (readonly) CDTypeFormatter *propertyTypeFormatter; 19 | @property (readonly) CDTypeFormatter *structDeclarationTypeFormatter; 20 | 21 | @property (nonatomic, readonly) BOOL shouldShowIvarOffsets; 22 | @property (nonatomic, readonly) BOOL shouldShowMethodAddresses; 23 | @property (nonatomic, readonly) BOOL targetArchUses64BitABI; 24 | 25 | @property (nonatomic, assign) BOOL hasUnknownFunctionPointers; 26 | @property (nonatomic, assign) BOOL hasUnknownBlocks; 27 | 28 | - (CDType *)typeFormatter:(CDTypeFormatter *)typeFormatter replacementForType:(CDType *)type; 29 | - (NSString *)typeFormatter:(CDTypeFormatter *)typeFormatter typedefNameForStructure:(CDType *)structureType level:(NSUInteger)level; 30 | - (void)typeFormatter:(CDTypeFormatter *)typeFormatter didReferenceClassName:(NSString *)name; 31 | - (void)typeFormatter:(CDTypeFormatter *)typeFormatter didReferenceProtocolNames:(NSArray *)names; 32 | 33 | - (void)appendStructuresToString:(NSMutableString *)resultString; 34 | 35 | // Phase 0 - initiated from -[CDClassDump registerTypes] 36 | - (void)phase0RegisterStructure:(CDType *)structure usedInMethod:(BOOL)isUsedInMethod; 37 | 38 | // Run phase 1+ 39 | - (void)workSomeMagic; 40 | 41 | // Phase 1 42 | - (void)phase1RegisterStructure:(CDType *)structure; 43 | 44 | - (void)endPhase:(NSUInteger)phase; 45 | 46 | - (CDType *)phase2ReplacementForType:(CDType *)type; 47 | 48 | - (void)phase3RegisterStructure:(CDType *)structure; 49 | - (CDType *)phase3ReplacementForType:(CDType *)type; 50 | 51 | - (BOOL)shouldShowName:(NSString *)name; 52 | - (BOOL)shouldExpandType:(CDType *)type; 53 | - (NSString *)typedefNameForType:(CDType *)type; 54 | 55 | @end 56 | 57 | #pragma mark - 58 | 59 | @protocol CDTypeControllerDelegate 60 | @optional 61 | - (void)typeController:(CDTypeController *)typeController didReferenceClassName:(NSString *)name; 62 | - (void)typeController:(CDTypeController *)typeController didReferenceProtocolNames:(NSArray *)names; 63 | @end 64 | -------------------------------------------------------------------------------- /Source/CDTypeFormatter.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType, CDTypeController; 7 | 8 | @interface CDTypeFormatter : NSObject 9 | 10 | @property (weak) CDTypeController *typeController; 11 | 12 | @property (assign) NSUInteger baseLevel; 13 | @property (assign) BOOL shouldExpand; 14 | @property (assign) BOOL shouldAutoExpand; 15 | @property (assign) BOOL shouldShowLexing; 16 | 17 | - (NSString *)formatVariable:(NSString *)name type:(CDType *)type; 18 | - (NSString *)formatMethodName:(NSString *)name typeString:(NSString *)typeString; 19 | 20 | - (NSString *)typedefNameForStructure:(CDType *)structureType level:(NSUInteger)level; 21 | 22 | - (void)formattingDidReferenceClassName:(NSString *)name; 23 | - (void)formattingDidReferenceProtocolNames:(NSArray *)names; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Source/CDTypeLexer.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #define TK_EOS 0 7 | #define TK_NUMBER 257 8 | #define TK_IDENTIFIER 258 9 | #define T_NAMED_OBJECT 259 10 | #define TK_QUOTED_STRING 260 11 | #define TK_TEMPLATE_TYPE TK_IDENTIFIER 12 | #define T_FUNCTION_POINTER_TYPE 1001 13 | #define T_BLOCK_TYPE 1002 14 | 15 | typedef enum : NSUInteger { 16 | CDTypeLexerState_Normal = 0, 17 | CDTypeLexerState_Identifier = 1, 18 | CDTypeLexerState_TemplateTypes = 2, 19 | } CDTypeLexerState; 20 | 21 | @interface CDTypeLexer : NSObject 22 | 23 | - (id)initWithString:(NSString *)string; 24 | 25 | @property (readonly) NSScanner *scanner; 26 | @property (nonatomic, assign) CDTypeLexerState state; 27 | @property (assign) BOOL shouldShowLexing; 28 | 29 | @property (nonatomic, readonly) NSString *string; 30 | - (int)scanNextToken; 31 | 32 | @property (strong) NSString *lexText; 33 | 34 | @property (nonatomic, readonly) unichar peekChar; 35 | @property (nonatomic, readonly) NSString *remainingString; 36 | @property (nonatomic, readonly) NSString *peekIdentifier; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /Source/CDTypeName.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface CDTypeName : NSObject 7 | 8 | @property (strong) NSString *name; 9 | @property (readonly) NSMutableArray *templateTypes; 10 | @property (strong) NSString *suffix; 11 | @property (nonatomic, readonly) BOOL isTemplateType; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Source/CDTypeName.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDTypeName.h" 7 | 8 | @implementation CDTypeName 9 | { 10 | NSString *_name; 11 | NSMutableArray *_templateTypes; 12 | NSString *_suffix; 13 | } 14 | 15 | - (id)init; 16 | { 17 | if ((self = [super init])) { 18 | _name = nil; 19 | _templateTypes = [[NSMutableArray alloc] init]; 20 | _suffix = nil; 21 | } 22 | 23 | return self; 24 | } 25 | 26 | #pragma mark - NSCopying 27 | 28 | - (id)copyWithZone:(NSZone *)zone; 29 | { 30 | CDTypeName *copy = [[CDTypeName alloc] init]; 31 | copy.name = self.name; 32 | copy.suffix = self.suffix; 33 | 34 | for (CDTypeName *subtype in self.templateTypes) { 35 | CDTypeName *subcopy = [subtype copy]; 36 | [copy.templateTypes addObject:subcopy]; 37 | } 38 | 39 | return copy; 40 | } 41 | 42 | #pragma mark - 43 | 44 | - (BOOL)isEqual:(id)otherObject; 45 | { 46 | if ([otherObject isKindOfClass:[self class]] == NO) 47 | return NO; 48 | 49 | return [[self description] isEqual:[otherObject description]]; 50 | } 51 | 52 | #pragma mark - Debugging 53 | 54 | - (NSString *)description; 55 | { 56 | if ([self.templateTypes count] == 0) { 57 | return self.name ? self.name : @""; 58 | } 59 | 60 | if (self.suffix != nil) 61 | return [NSString stringWithFormat:@"%@<%@>%@", self.name, [self.templateTypes componentsJoinedByString:@", "], self.suffix]; 62 | 63 | return [NSString stringWithFormat:@"%@<%@>", self.name, [self.templateTypes componentsJoinedByString:@", "]]; 64 | } 65 | 66 | #pragma mark - 67 | 68 | - (BOOL)isTemplateType; 69 | { 70 | return [self.templateTypes count] > 0; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Source/CDTypeParser.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDType, CDTypeLexer; 7 | 8 | extern NSString *CDExceptionName_SyntaxError; 9 | extern NSString *CDErrorDomain_TypeParser; 10 | 11 | extern NSString *CDErrorKey_Type; 12 | extern NSString *CDErrorKey_RemainingString; 13 | extern NSString *CDErrorKey_MethodOrVariable; 14 | extern NSString *CDErrorKey_LocalizedLongDescription; 15 | 16 | #define CDTypeParserCode_Default 0 17 | #define CDTypeParserCode_SyntaxError 1 18 | 19 | @interface CDTypeParser : NSObject 20 | 21 | - (id)initWithString:(NSString *)string; 22 | 23 | @property (readonly) CDTypeLexer *lexer; 24 | 25 | - (NSArray *)parseMethodType:(NSError **)error; 26 | - (CDType *)parseType:(NSError **)error; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Source/CDVisitor.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDClassDump, CDObjectiveCProcessor, CDOCProtocol, CDOCMethod, CDOCInstanceVariable, CDOCClass, CDOCCategory, CDOCProperty; 7 | @class CDVisitorPropertyState; 8 | 9 | @interface CDVisitor : NSObject 10 | 11 | @property (strong) CDClassDump *classDump; 12 | 13 | - (void)willBeginVisiting; 14 | - (void)didEndVisiting; 15 | 16 | - (void)willVisitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 17 | - (void)visitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 18 | - (void)didVisitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 19 | 20 | - (void)willVisitProtocol:(CDOCProtocol *)protocol; 21 | - (void)didVisitProtocol:(CDOCProtocol *)protocol; 22 | 23 | - (void)willVisitPropertiesOfProtocol:(CDOCProtocol *)protocol; 24 | - (void)didVisitPropertiesOfProtocol:(CDOCProtocol *)protocol; 25 | 26 | - (void)willVisitOptionalMethods; 27 | - (void)didVisitOptionalMethods; 28 | 29 | - (void)willVisitClass:(CDOCClass *)aClass; 30 | - (void)didVisitClass:(CDOCClass *)aClass; 31 | 32 | - (void)willVisitIvarsOfClass:(CDOCClass *)aClass; 33 | - (void)didVisitIvarsOfClass:(CDOCClass *)aClass; 34 | 35 | - (void)willVisitPropertiesOfClass:(CDOCClass *)aClass; 36 | - (void)didVisitPropertiesOfClass:(CDOCClass *)aClass; 37 | 38 | - (void)willVisitCategory:(CDOCCategory *)category; 39 | - (void)didVisitCategory:(CDOCCategory *)category; 40 | 41 | - (void)willVisitPropertiesOfCategory:(CDOCCategory *)category; 42 | - (void)didVisitPropertiesOfCategory:(CDOCCategory *)category; 43 | 44 | - (void)visitClassMethod:(CDOCMethod *)method; 45 | - (void)visitInstanceMethod:(CDOCMethod *)method propertyState:(CDVisitorPropertyState *)propertyState; 46 | - (void)visitIvar:(CDOCInstanceVariable *)ivar; 47 | - (void)visitProperty:(CDOCProperty *)property; 48 | 49 | - (void)visitRemainingProperties:(CDVisitorPropertyState *)propertyState; 50 | 51 | @property (assign) BOOL shouldShowStructureSection; 52 | @property (assign) BOOL shouldShowProtocolSection; 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /Source/CDVisitor.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDVisitor.h" 7 | 8 | #import "CDClassDump.h" 9 | 10 | @implementation CDVisitor 11 | { 12 | CDClassDump *_classDump; 13 | BOOL _shouldShowStructureSection; 14 | BOOL _shouldShowProtocolSection; 15 | } 16 | 17 | - (id)init; 18 | { 19 | if ((self = [super init])) { 20 | _shouldShowStructureSection = YES; 21 | _shouldShowProtocolSection = YES; 22 | } 23 | 24 | return self; 25 | } 26 | 27 | #pragma mark - 28 | 29 | - (void)willBeginVisiting; 30 | { 31 | } 32 | 33 | - (void)didEndVisiting; 34 | { 35 | } 36 | 37 | // Called before visiting. 38 | - (void)willVisitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 39 | { 40 | } 41 | 42 | // This gets called before visiting the children, but only if it has children it will visit. 43 | - (void)visitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 44 | { 45 | } 46 | 47 | - (void)willVisitPropertiesOfProtocol:(CDOCProtocol *)protocol; 48 | { 49 | } 50 | 51 | - (void)didVisitPropertiesOfProtocol:(CDOCProtocol *)protocol; 52 | { 53 | } 54 | 55 | - (void)willVisitOptionalMethods; 56 | { 57 | } 58 | 59 | - (void)didVisitOptionalMethods; 60 | { 61 | } 62 | 63 | // Called after visiting. 64 | - (void)didVisitObjectiveCProcessor:(CDObjectiveCProcessor *)processor; 65 | { 66 | } 67 | 68 | - (void)willVisitProtocol:(CDOCProtocol *)protocol; 69 | { 70 | } 71 | 72 | - (void)didVisitProtocol:(CDOCProtocol *)protocol; 73 | { 74 | } 75 | 76 | - (void)willVisitClass:(CDOCClass *)aClass; 77 | { 78 | } 79 | 80 | - (void)didVisitClass:(CDOCClass *)aClass; 81 | { 82 | } 83 | 84 | - (void)willVisitIvarsOfClass:(CDOCClass *)aClass; 85 | { 86 | } 87 | 88 | - (void)didVisitIvarsOfClass:(CDOCClass *)aClass; 89 | { 90 | } 91 | 92 | - (void)willVisitPropertiesOfClass:(CDOCClass *)aClass; 93 | { 94 | } 95 | 96 | - (void)didVisitPropertiesOfClass:(CDOCClass *)aClass; 97 | { 98 | } 99 | 100 | - (void)willVisitCategory:(CDOCCategory *)category; 101 | { 102 | } 103 | 104 | - (void)didVisitCategory:(CDOCCategory *)category; 105 | { 106 | } 107 | 108 | - (void)willVisitPropertiesOfCategory:(CDOCCategory *)category; 109 | { 110 | } 111 | 112 | - (void)didVisitPropertiesOfCategory:(CDOCCategory *)category; 113 | { 114 | } 115 | 116 | - (void)visitClassMethod:(CDOCMethod *)method; 117 | { 118 | } 119 | 120 | - (void)visitInstanceMethod:(CDOCMethod *)method propertyState:(CDVisitorPropertyState *)propertyState; 121 | { 122 | } 123 | 124 | - (void)visitIvar:(CDOCInstanceVariable *)ivar; 125 | { 126 | } 127 | 128 | - (void)visitProperty:(CDOCProperty *)property; 129 | { 130 | } 131 | 132 | - (void)visitRemainingProperties:(CDVisitorPropertyState *)propertyState; 133 | { 134 | } 135 | 136 | @end 137 | -------------------------------------------------------------------------------- /Source/CDVisitorPropertyState.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @class CDOCProperty; 7 | 8 | @interface CDVisitorPropertyState : NSObject 9 | 10 | - (id)initWithProperties:(NSArray *)properties; 11 | 12 | - (CDOCProperty *)propertyForAccessor:(NSString *)str; 13 | 14 | - (BOOL)hasUsedProperty:(CDOCProperty *)property; 15 | - (void)useProperty:(CDOCProperty *)property; 16 | 17 | @property (nonatomic, readonly) NSArray *remainingProperties; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Source/CDVisitorPropertyState.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "CDVisitorPropertyState.h" 7 | 8 | #import "CDOCProperty.h" 9 | 10 | @interface CDVisitorPropertyState () 11 | @end 12 | 13 | #pragma mark - 14 | 15 | @implementation CDVisitorPropertyState 16 | { 17 | NSMutableDictionary *_propertiesByAccessor; // NSString (accessor) -> CDOCProperty 18 | NSMutableDictionary *_propertiesByName; // NSString (property name) -> CDOCProperty 19 | } 20 | 21 | - (id)initWithProperties:(NSArray *)properties; 22 | { 23 | if ((self = [super init])) { 24 | _propertiesByAccessor = [[NSMutableDictionary alloc] init]; 25 | _propertiesByName = [[NSMutableDictionary alloc] init]; 26 | 27 | for (CDOCProperty *property in properties) { 28 | //NSLog(@"property: %@, getter: %@, setter: %@", [property name], [property getter], [property setter]); 29 | _propertiesByName[property.name] = property; 30 | _propertiesByAccessor[property.getter] = property; 31 | if (property.isReadOnly == NO) 32 | _propertiesByAccessor[property.setter] = property; 33 | } 34 | } 35 | 36 | return self; 37 | } 38 | 39 | #pragma mark - Debugging 40 | 41 | - (void)log; 42 | { 43 | NSLog(@"propertiesByAccessor: %@", _propertiesByAccessor); 44 | NSLog(@"propertiesByName: %@", _propertiesByName); 45 | } 46 | 47 | #pragma mark - 48 | 49 | - (CDOCProperty *)propertyForAccessor:(NSString *)str; 50 | { 51 | return _propertiesByAccessor[str]; 52 | } 53 | 54 | - (BOOL)hasUsedProperty:(CDOCProperty *)property; 55 | { 56 | return _propertiesByName[property.name] == nil; 57 | } 58 | 59 | - (void)useProperty:(CDOCProperty *)property; 60 | { 61 | [_propertiesByName removeObjectForKey:property.name]; 62 | } 63 | 64 | - (NSArray *)remainingProperties; 65 | { 66 | return [[_propertiesByName allValues] sortedArrayUsingSelector:@selector(ascendingCompareByName:)]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Source/NSArray-CDExtensions.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface NSArray (CDExtensions) 7 | 8 | - (NSArray *)reversedArray; 9 | 10 | @end 11 | 12 | @interface NSArray (CDTopoSort) 13 | 14 | - (NSArray *)topologicallySortedArray; 15 | 16 | @end 17 | 18 | @interface NSMutableArray (CDTopoSort) 19 | 20 | - (void)sortTopologically; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Source/NSArray-CDExtensions.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "NSArray-CDExtensions.h" 7 | 8 | @implementation NSArray (CDExtensions) 9 | 10 | - (NSArray *)reversedArray; 11 | { 12 | return [[self reverseObjectEnumerator] allObjects]; 13 | } 14 | 15 | @end 16 | 17 | #pragma mark - 18 | 19 | @implementation NSArray (CDTopoSort) 20 | 21 | - (NSArray *)topologicallySortedArray; 22 | { 23 | NSMutableDictionary *nodesByName = [[NSMutableDictionary alloc] init]; 24 | 25 | for (id object in self) { 26 | CDTopoSortNode *node = [[CDTopoSortNode alloc] initWithObject:object]; 27 | [node addDependanciesFromArray:[object dependancies]]; 28 | 29 | if (nodesByName[node.identifier] != nil) 30 | NSLog(@"Warning: Duplicate identifier (%@) in %s", node.identifier, __cmd); 31 | nodesByName[node.identifier] = node; 32 | } 33 | 34 | NSMutableArray *sortedArray = [NSMutableArray array]; 35 | 36 | NSArray *allNodes = [[nodesByName allValues] sortedArrayUsingSelector:@selector(ascendingCompareByIdentifier:)]; 37 | for (CDTopoSortNode *node in allNodes) { 38 | if (node.color == CDNodeColor_White) 39 | [node topologicallySortNodes:nodesByName intoArray:sortedArray]; 40 | } 41 | 42 | 43 | return sortedArray; 44 | } 45 | 46 | @end 47 | 48 | #pragma mark - 49 | 50 | @implementation NSMutableArray (CDTopoSort) 51 | 52 | - (void)sortTopologically; 53 | { 54 | NSArray *sortedArray = [self topologicallySortedArray]; 55 | assert([self count] == [sortedArray count]); 56 | 57 | [self removeAllObjects]; 58 | [self addObjectsFromArray:sortedArray]; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Source/NSData-CDExtensions.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface NSData (CDExtensions) 7 | 8 | - (NSString *)hexString; 9 | - (NSData *)SHA1Digest; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /Source/NSData-CDExtensions.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "NSData-CDExtensions.h" 7 | 8 | #import 9 | 10 | @implementation NSData (CDExtensions) 11 | 12 | - (NSString *)hexString; 13 | { 14 | NSMutableString *str = [NSMutableString string]; 15 | const uint8_t *ptr = [self bytes]; 16 | for (NSUInteger index = 0; index < [self length]; index++) { 17 | [str appendFormat:@"%02x", *ptr++]; 18 | } 19 | 20 | return str; 21 | } 22 | 23 | - (NSData *)SHA1Digest; 24 | { 25 | NSParameterAssert([self length] <= UINT32_MAX); 26 | 27 | unsigned char digest[CC_SHA1_DIGEST_LENGTH]; 28 | CC_SHA1([self bytes], (CC_LONG)[self length], digest); 29 | 30 | return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Source/NSError-CDExtensions.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface NSError (CDExtensions) 7 | 8 | @end 9 | 10 | extern NSString *NSErrorDomain_ClassDump; 11 | -------------------------------------------------------------------------------- /Source/NSError-CDExtensions.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "NSError-CDExtensions.h" 7 | 8 | NSString *NSErrorDomain_ClassDump = @"com.stevenygard.MachObjC.ErrorDomain"; 9 | 10 | @implementation NSError (CDExtensions) 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Source/NSScanner-CDExtensions.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface NSScanner (CDExtensions) 7 | 8 | + (NSCharacterSet *)cdOtherCharacterSet; 9 | + (NSCharacterSet *)cdIdentifierStartCharacterSet; 10 | + (NSCharacterSet *)cdIdentifierCharacterSet; 11 | + (NSCharacterSet *)cdTemplateTypeCharacterSet; 12 | 13 | - (NSString *)peekCharacter; 14 | - (unichar)peekChar; 15 | - (BOOL)scanCharacter:(unichar *)value; 16 | - (BOOL)scanCharacterFromSet:(NSCharacterSet *)set intoString:(NSString **)value; 17 | - (BOOL)my_scanCharactersFromSet:(NSCharacterSet *)set intoString:(NSString **)value; 18 | 19 | - (BOOL)scanIdentifierIntoString:(NSString **)stringPointer; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Source/NSString-CDExtensions.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | @interface NSString (CDExtensions) 7 | 8 | + (NSString *)stringWithFileSystemRepresentation:(const char *)str; 9 | + (NSString *)spacesIndentedToLevel:(NSUInteger)level; 10 | + (NSString *)spacesIndentedToLevel:(NSUInteger)level spacesPerLevel:(NSUInteger)spacesPerLevel; 11 | + (NSString *)stringWithUnichar:(unichar)character; 12 | 13 | - (BOOL)isFirstLetterUppercase; 14 | 15 | - (void)print; 16 | 17 | - (NSString *)executablePathForFilename; 18 | 19 | - (NSString *)SHA1DigestString; 20 | 21 | - (BOOL)hasUnderscoreCapitalPrefix; 22 | - (NSString *)capitalizeFirstCharacter; 23 | 24 | @end 25 | 26 | @interface NSMutableString (CDExtensions) 27 | 28 | - (void)appendSpacesIndentedToLevel:(NSUInteger)level; 29 | - (void)appendSpacesIndentedToLevel:(NSUInteger)level spacesPerLevel:(NSUInteger)spacesPerLevel; 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /Source/ULEB128.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | // http://en.wikipedia.org/wiki/LEB128 7 | // http://web.mit.edu/rhel-doc/3/rhel-as-en-3/uleb128.html 8 | // uleb128 stands for "unsigned little endian base 128." 9 | // This is a compact, variable length representation of numbers used by the DWARF symbolic debugging format. 10 | 11 | // Top bit of byte is set until last byte. 12 | // Other 7 bits are the "slice". 13 | // Basically, it represents the low order bits 7 at a time, and can stop when the rest of the bits would be zero. 14 | // This needs to modify ptr. 15 | 16 | // For example, uleb with these bytes: e8 d7 15 17 | // 0xe8 = 1110 1000 18 | // 0xd7 = 1101 0111 19 | // 0x15 = 0001 0101 20 | 21 | // .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... 22 | // 0xe8 1 1101000 .... .... .... .... .... .... .... .... .... .... .... .... .... .... .110 1000 23 | // 0xd7 1 1010111 .... .... .... .... .... .... .... .... .... .... .... .... ..10 1011 1110 1000 24 | // 0x15 0 0010101 .... .... .... .... .... .... .... .... .... .... .... .... ..10 1011 1110 1000 25 | // 0x15 0 0010101 .... .... .... .... .... .... .... .... .... .... ...0 0101 0110 1011 1110 1000 26 | // Result is: 0x056be8 27 | // So... 24 bits to encode 64 bits 28 | 29 | uint64_t read_uleb128(const uint8_t **ptrptr, const uint8_t *end); 30 | 31 | int64_t read_sleb128(const uint8_t **ptrptr, const uint8_t *end); 32 | -------------------------------------------------------------------------------- /Source/ULEB128.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import "ULEB128.h" 7 | 8 | uint64_t read_uleb128(const uint8_t **ptrptr, const uint8_t *end) 9 | { 10 | const uint8_t *ptr = *ptrptr; 11 | uint64_t result = 0; 12 | int bit = 0; 13 | 14 | //NSLog(@"read_uleb128()"); 15 | do { 16 | NSCAssert(ptr != end, @"Malformed uleb128", nil); 17 | 18 | //NSLog(@"byte: %02x", *ptr); 19 | uint64_t slice = *ptr & 0x7f; 20 | 21 | if (bit >= 64 || slice << bit >> bit != slice) { 22 | NSLog(@"uleb128 too big"); 23 | exit(88); 24 | } else { 25 | result |= (slice << bit); 26 | bit += 7; 27 | } 28 | } 29 | while ((*ptr++ & 0x80) != 0); 30 | 31 | #if 0 32 | static NSUInteger maxlen = 0; 33 | if (maxlen < ptr - *ptrptr) { 34 | const uint8_t *ptr2 = *ptrptr; 35 | 36 | NSMutableArray *byteStrs = [NSMutableArray array]; 37 | do { 38 | [byteStrs addObject:[NSString stringWithFormat:@"%02x", *ptr2]]; 39 | } while (++ptr2 < ptr); 40 | //NSLog(@"max uleb length now: %u (%@)", ptr - *ptrptr, [byteStrs componentsJoinedByString:@" "]); 41 | //NSLog(@"sizeof(uint64_t): %u, sizeof(uintptr_t): %u", sizeof(uint64_t), sizeof(uintptr_t)); 42 | maxlen = ptr - *ptrptr; 43 | } 44 | #endif 45 | 46 | *ptrptr = ptr; 47 | return result; 48 | } 49 | 50 | int64_t read_sleb128(const uint8_t **ptrptr, const uint8_t *end) 51 | { 52 | const uint8_t *ptr = *ptrptr; 53 | 54 | int64_t result = 0; 55 | int bit = 0; 56 | uint8_t byte; 57 | 58 | //NSLog(@"read_sleb128()"); 59 | do { 60 | NSCAssert(ptr != end, @"Malformed sleb128", nil); 61 | 62 | byte = *ptr++; 63 | //NSLog(@"%02x", byte); 64 | result |= ((byte & 0x7f) << bit); 65 | bit += 7; 66 | } while ((byte & 0x80) != 0); 67 | 68 | //NSLog(@"result before sign extend: %ld", result); 69 | // sign extend negative numbers 70 | // This essentially clears out from -1 the low order bits we've already set, and combines that with our bits. 71 | if ( (byte & 0x40) != 0 ) 72 | result |= (-1LL) << bit; 73 | 74 | //NSLog(@"result after sign extend: %ld", result); 75 | 76 | //NSLog(@"ptr before: %p, after: %p", *ptrptr, ptr); 77 | *ptrptr = ptr; 78 | return result; 79 | } 80 | -------------------------------------------------------------------------------- /Source/cd_objc2.h: -------------------------------------------------------------------------------- 1 | struct cd_objc2_list_header { 2 | uint32_t entsize; 3 | uint32_t count; 4 | }; 5 | 6 | struct cd_objc2_image_info { 7 | uint32_t version; 8 | uint32_t flags; 9 | }; 10 | 11 | 12 | // 13 | // 64-bit, also holding 32-bit 14 | // 15 | 16 | struct cd_objc2_class { 17 | uint64_t isa; 18 | uint64_t superclass; 19 | uint64_t cache; 20 | uint64_t vtable; 21 | uint64_t data; // points to class_ro_t 22 | uint64_t reserved1; 23 | uint64_t reserved2; 24 | uint64_t reserved3; 25 | }; 26 | 27 | struct cd_objc2_class_ro_t { 28 | uint32_t flags; 29 | uint32_t instanceStart; 30 | uint32_t instanceSize; 31 | uint32_t reserved; // *** this field does not exist in the 32-bit version *** 32 | uint64_t ivarLayout; 33 | uint64_t name; 34 | uint64_t baseMethods; 35 | uint64_t baseProtocols; 36 | uint64_t ivars; 37 | uint64_t weakIvarLayout; 38 | uint64_t baseProperties; 39 | }; 40 | 41 | struct cd_objc2_method { 42 | uint64_t name; 43 | uint64_t types; 44 | uint64_t imp; 45 | }; 46 | 47 | struct cd_objc2_ivar { 48 | uint64_t offset; 49 | uint64_t name; 50 | uint64_t type; 51 | uint32_t alignment; 52 | uint32_t size; 53 | }; 54 | 55 | struct cd_objc2_property { 56 | uint64_t name; 57 | uint64_t attributes; 58 | }; 59 | 60 | struct cd_objc2_protocol { 61 | uint64_t isa; 62 | uint64_t name; 63 | uint64_t protocols; 64 | uint64_t instanceMethods; 65 | uint64_t classMethods; 66 | uint64_t optionalInstanceMethods; 67 | uint64_t optionalClassMethods; 68 | uint64_t instanceProperties; // So far, always 0 69 | uint32_t size; // sizeof(cd_objc2_protocol) 70 | uint32_t flags; 71 | uint64_t extendedMethodTypes; 72 | }; 73 | 74 | struct cd_objc2_category { 75 | uint64_t name; 76 | uint64_t class; 77 | uint64_t instanceMethods; 78 | uint64_t classMethods; 79 | uint64_t protocols; 80 | uint64_t instanceProperties; 81 | uint64_t v7; 82 | uint64_t v8; 83 | }; 84 | -------------------------------------------------------------------------------- /Tests/showdiff: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | pushd /tmp/cdt/new 4 | foreach i (*.txt) 5 | echo -e "\\033[32m" 6 | echo $i 7 | echo -e "\\033[0m" 8 | diff ../old/$i $i | colordiff.pl 9 | echo 10 | echo 11 | echo 12 | 13 | end 14 | -------------------------------------------------------------------------------- /ThirdParty/blowfish.h: -------------------------------------------------------------------------------- 1 | /* 2 | blowfish.h: Header file for blowfish.c 3 | 4 | Copyright (C) 1997 by Paul Kocher 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | 18 | 19 | See blowfish.c for more information about this file. 20 | */ 21 | 22 | #include 23 | 24 | typedef struct { 25 | uint32_t P[16 + 2]; 26 | uint32_t S[4][256]; 27 | } BLOWFISH_CTX; 28 | 29 | void Blowfish_Init(BLOWFISH_CTX *ctx, uint8_t *key, int32_t keyLen); 30 | void Blowfish_Encrypt(BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr); 31 | void Blowfish_Decrypt(BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr); 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /UnitTests.old/AllTests.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | #import 4 | 5 | @interface AllTests : SenTestCase 6 | { 7 | } 8 | 9 | + (id)defaultTestSuite; 10 | 11 | @end 12 | -------------------------------------------------------------------------------- /UnitTests.old/CDPathUnitTest.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | @class CDClassDump; 9 | 10 | @interface CDPathUnitTest : SenTestCase 11 | { 12 | CDClassDump *classDump; 13 | } 14 | 15 | - (void)setUp; 16 | - (void)tearDown; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /UnitTests.old/CDPathUnitTest.m: -------------------------------------------------------------------------------- 1 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 2 | // Copyright (C) 1997-2019 Steve Nygard. 3 | 4 | #import "CDPathUnitTest.h" 5 | 6 | #import 7 | #import "CDClassDump.h" 8 | 9 | @implementation CDPathUnitTest 10 | 11 | - (void)setUp; 12 | { 13 | classDump = [[CDClassDump alloc] init]; 14 | } 15 | 16 | - (void)tearDown; 17 | { 18 | [classDump release]; 19 | classDump = nil; 20 | } 21 | 22 | - (void)testPrivateSyncFramework; 23 | { 24 | NSString *path = @"/System/Library/PrivateFrameworks/SyndicationUI.framework"; 25 | NSBundle *bundle; 26 | 27 | bundle = [NSBundle bundleWithPath:path]; 28 | STAssertNotNil(bundle, @"%@ doesn't seem to exist, we can remove this test now.", path); 29 | if (bundle != nil) { 30 | STAssertNil([bundle executablePath], @"This fails on 10.5. It's fixed if you see this! Executable path for %@", path); 31 | //STAssertNotNil([bundle executablePath], @"This fails on 10.5. Executable path for %@", path); 32 | } 33 | } 34 | 35 | - (void)testBundlePathWithoutTrailingSlash; 36 | { 37 | BOOL result; 38 | 39 | result = [classDump processFilename:@"/System/Library/Frameworks/AppKit.framework"]; 40 | STAssertEquals(YES, result, @"Couldn't process AppKit.framework"); 41 | STAssertEqualObjects(@"/System/Library/Frameworks/AppKit.framework/Versions/C", [classDump executablePath], @""); 42 | } 43 | 44 | - (void)testBundlePathWithTrailingSlash; 45 | { 46 | BOOL result; 47 | 48 | result = [classDump processFilename:@"/System/Library/Frameworks/AppKit.framework/"]; 49 | STAssertEquals(YES, result, @"Couldn't process AppKit.framework"); 50 | STAssertEqualObjects(@"/System/Library/Frameworks/AppKit.framework/Versions/C", [classDump executablePath], @""); 51 | } 52 | 53 | - (void)testExecutableSymlinkPath; 54 | { 55 | BOOL result; 56 | 57 | result = [classDump processFilename:@"/System/Library/Frameworks/AppKit.framework/AppKit"]; 58 | STAssertEquals(YES, result, @"Couldn't process AppKit.framework"); 59 | STAssertEqualObjects(@"/System/Library/Frameworks/AppKit.framework/Versions/C", [classDump executablePath], @""); 60 | } 61 | 62 | - (void)testExecutableFullPath; 63 | { 64 | BOOL result; 65 | 66 | result = [classDump processFilename:@"/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit"]; 67 | STAssertEquals(YES, result, @"Couldn't process AppKit.framework"); 68 | STAssertEqualObjects(@"/System/Library/Frameworks/AppKit.framework/Versions/C", [classDump executablePath], @""); 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /UnitTests.old/CDStructHandlingUnitTest.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | @class CDClassDump; 9 | 10 | @interface CDStructHandlingUnitTest : SenTestCase 11 | { 12 | CDClassDump *classDump; 13 | } 14 | 15 | - (void)dealloc; 16 | 17 | - (void)setUp; 18 | - (void)tearDown; 19 | 20 | - (void)testVariableName:(NSString *)aVariableName type:(NSString *)aType expectedResult:(NSString *)expectedResult; 21 | - (void)registerStructsFromType:(NSString *)aTypeString phase:(int)phase; 22 | 23 | - (void)testFilename:(NSString *)testFilename; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /UnitTests.old/CDTypeFormatterUnitTest.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | @class CDTypeFormatter; 9 | 10 | @interface CDTypeFormatterUnitTest : SenTestCase 11 | { 12 | CDTypeFormatter *typeFormatter; 13 | } 14 | 15 | - (void)dealloc; 16 | 17 | - (void)setUp; 18 | - (void)tearDown; 19 | 20 | - (void)testVariableName:(NSString *)aVariableName type:(NSString *)aType expectedResult:(NSString *)expectedResult; 21 | - (void)parseAndEncodeType:(NSString *)originalType; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /UnitTests.old/CDTypeLexerUnitTest.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | @class CDTypeLexer; 9 | 10 | @interface CDTypeLexerUnitTest : SenTestCase 11 | { 12 | CDTypeLexer *lexer; 13 | } 14 | 15 | - (void)setUp; 16 | - (void)tearDown; 17 | 18 | - (void)_setupLexerForString:(NSString *)str; 19 | - (void)_cleanupLexer; 20 | - (void)_showScannedTokens; 21 | - (void)showScannedTokensForString:(NSString *)str; 22 | 23 | - (void)testLexingString:(NSString *)str expectedResults:(struct tokenValuePair *)expectedResults; 24 | 25 | - (void)testSimpleTokens; 26 | - (void)testQuotedStringToken; 27 | - (void)testEmptyQuotedStringToken; 28 | - (void)testUnterminatedQuotedString; 29 | - (void)testIdentifierToken; 30 | - (void)testTemplateTokens; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /UnitTests.old/CDTypeParserUnitTest.h: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | @interface CDTypeParserUnitTest : SenTestCase 9 | { 10 | } 11 | 12 | - (void)setUp; 13 | - (void)tearDown; 14 | 15 | - (void)testType:(NSString *)aType showLexing:(BOOL)shouldShowLexing; 16 | - (void)testMethodType:(NSString *)aMethodType showLexing:(BOOL)shouldShowLexing; 17 | 18 | - (void)testLoneConstType; 19 | - (void)testObjectQuotedStringTypes; 20 | 21 | - (void)testMissingFieldNames; 22 | - (void)testLowercaseClassName; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /UnitTests.old/method-001.txt: -------------------------------------------------------------------------------- 1 | // This comes from Safari 4.0.2 on Mac OS 10.5 2 | // The problem here was with the trailing * after the template type name. 3 | 4 | initWithBookmarkGroup: 5 | @12@0:4^{BookmarkGroup=B{SString={RetainPtr=^{__CFString}}}{SString={RetainPtr=^{__CFString}}}B{HashMap, 0ul>*,Safari::SCFObjectSubclassHash,WTF::HashTraits,WTF::HashTraits, 0ul>*> >={HashTable, 0ul>*>,WTF::PairFirstExtractor, 0ul>*> >,Safari::SCFObjectSubclassHash,WTF::PairHashTraits, WTF::HashTraits, 0ul>*> >,WTF::HashTraits >=^{pair, 0ul>*>}iiii}}{HashMap,Safari::SCFObjectSubclassHash,WTF::HashTraits,WTF::HashTraits > >={HashTable >,WTF::PairFirstExtractor > >,Safari::SCFObjectSubclassHash,WTF::PairHashTraits, WTF::HashTraits > >,WTF::HashTraits >=^{pair >}iiii}}BB{RetainPtr=@}{RetainPtr=@}}8 6 | -------------------------------------------------------------------------------- /UnitTests.old/otest-all: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "${OTEST_TEST_CLASS}" = "" ]; then 4 | OTEST_TEST_CLASS="AllTests" 5 | fi 6 | 7 | ${DEVELOPER_DIR}/Tools/otest -SenTest ${OTEST_TEST_CLASS} $* 8 | -------------------------------------------------------------------------------- /UnitTests.old/shud01-in.txt: -------------------------------------------------------------------------------- 1 | // This tests a simple structure without field names. 2 | {_NSRange=II} foo 3 | -------------------------------------------------------------------------------- /UnitTests.old/shud01-out.txt: -------------------------------------------------------------------------------- 1 | struct _NSRange { 2 | unsigned int; 3 | unsigned int; 4 | }; 5 | 6 | struct _NSRange foo; 7 | -------------------------------------------------------------------------------- /UnitTests.old/shud02-in.txt: -------------------------------------------------------------------------------- 1 | // This tests recognizing that two structures, one with field names and the other without, are really the same. 2 | {_NSRange=II} foo 3 | {_NSRange="location"I"length"I} bar 4 | -------------------------------------------------------------------------------- /UnitTests.old/shud02-out.txt: -------------------------------------------------------------------------------- 1 | struct _NSRange { 2 | unsigned int location; 3 | unsigned int length; 4 | }; 5 | 6 | struct _NSRange foo; 7 | struct _NSRange bar; 8 | -------------------------------------------------------------------------------- /UnitTests.old/shud04-in.txt: -------------------------------------------------------------------------------- 1 | // This tests a common structure that contains two other structures. 2 | // Note: It looks like struct _NSSize is shown after _NSRect, but it should really be before it. 3 | {_NSRect={_NSPoint=ff}{_NSSize=ff}} 4 | -------------------------------------------------------------------------------- /UnitTests.old/shud04-out.txt: -------------------------------------------------------------------------------- 1 | struct _NSPoint { 2 | float; 3 | float; 4 | }; 5 | 6 | struct _NSRect { 7 | struct _NSPoint; 8 | struct _NSSize; 9 | }; 10 | 11 | struct _NSSize { 12 | float; 13 | float; 14 | }; 15 | 16 | struct _NSRect var; 17 | -------------------------------------------------------------------------------- /UnitTests.old/shud05-in.txt: -------------------------------------------------------------------------------- 1 | {one="field1"i"field2"c"field3"{?=ff}} 2 | -------------------------------------------------------------------------------- /UnitTests.old/shud05-out.txt: -------------------------------------------------------------------------------- 1 | struct one { 2 | int field1; 3 | char field2; 4 | struct { 5 | float; 6 | float; 7 | } field3; 8 | }; 9 | 10 | struct one var; 11 | -------------------------------------------------------------------------------- /UnitTests.old/shud06-in.txt: -------------------------------------------------------------------------------- 1 | {one="field1"i"field2"c"field3"{?=ff}} 2 | {one="field1"i"field2"c"field3"{?="x"f"y"f}} 3 | -------------------------------------------------------------------------------- /UnitTests.old/shud06-out.txt: -------------------------------------------------------------------------------- 1 | struct one { 2 | int field1; 3 | char field2; 4 | struct { 5 | float x; 6 | float y; 7 | } field3; 8 | }; 9 | 10 | struct one var; 11 | struct one var; 12 | -------------------------------------------------------------------------------- /UnitTests.old/shud07-in.txt: -------------------------------------------------------------------------------- 1 | {one="field1"i"field2"c"field3"{?="x"f"y"f}} 2 | {one="field1"i"field2"c"field3"{?="x"f"y"f}} 3 | -------------------------------------------------------------------------------- /UnitTests.old/shud07-out.txt: -------------------------------------------------------------------------------- 1 | struct one { 2 | int field1; 3 | char field2; 4 | struct { 5 | float x; 6 | float y; 7 | } field3; 8 | }; 9 | 10 | struct one var; 11 | struct one var; 12 | -------------------------------------------------------------------------------- /UnitTests.old/shud08-in.txt: -------------------------------------------------------------------------------- 1 | {one="field1"i"field2"c"field3"{?="x"f"y"f}} 2 | {one="field1"i"field2"c"field3"{?="x"f"y"f}} 3 | {?="x"f"y"f} 4 | -------------------------------------------------------------------------------- /UnitTests.old/shud08-out.txt: -------------------------------------------------------------------------------- 1 | struct one { 2 | int field1; 3 | char field2; 4 | CDAnonymousStruct1 field3; 5 | }; 6 | 7 | typedef struct { 8 | float x; 9 | float y; 10 | } CDAnonymousStruct1; 11 | 12 | struct one var; 13 | struct one var; 14 | CDAnonymousStruct1 var; 15 | -------------------------------------------------------------------------------- /UnitTests.old/shud09-in.txt: -------------------------------------------------------------------------------- 1 | // Test a structure that contains one of many common types. The first type has member names, the second doesn't, but they're the same. 2 | {?="type"i"value"(?="charValue"c"shortValue"s"longValue"l"longlongValue"q"floatValue"f"doubleValue"d"boolValue"B"selectorValue":"objectValue"@"pointerValue"^v"structLocation"^v"cStringLocation"*)} 3 | {?=i(?=cslqfdB:@^v^v*)} 4 | -------------------------------------------------------------------------------- /UnitTests.old/shud09-out.txt: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | int type; 3 | union { 4 | char charValue; 5 | short shortValue; 6 | long longValue; 7 | long long longlongValue; 8 | float floatValue; 9 | double doubleValue; 10 | _Bool boolValue; 11 | SEL selectorValue; 12 | id objectValue; 13 | void *pointerValue; 14 | void *structLocation; 15 | char *cStringLocation; 16 | } value; 17 | } CDAnonymousStruct1; 18 | 19 | CDAnonymousStruct1 var; 20 | CDAnonymousStruct1 var; 21 | -------------------------------------------------------------------------------- /UnitTests.old/shud10-in.txt: -------------------------------------------------------------------------------- 1 | {?="field1"i"field2"i} 2 | {?=ii} 3 | -------------------------------------------------------------------------------- /UnitTests.old/shud10-out.txt: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | int field1; 3 | int field2; 4 | } CDAnonymousStruct1; 5 | 6 | CDAnonymousStruct1 var; 7 | CDAnonymousStruct1 var; 8 | -------------------------------------------------------------------------------- /UnitTests.old/shud11-in.txt: -------------------------------------------------------------------------------- 1 | {?="field1"i"field2"i} 2 | {?=ii} 3 | {?="bar1"i"bar2"i} 4 | -------------------------------------------------------------------------------- /UnitTests.old/shud11-out.txt: -------------------------------------------------------------------------------- 1 | struct { 2 | int field1; 3 | int field2; 4 | } var; 5 | struct { 6 | int; 7 | int; 8 | } var; 9 | struct { 10 | int bar1; 11 | int bar2; 12 | } var; 13 | -------------------------------------------------------------------------------- /UnitTests.old/shud13-in.txt: -------------------------------------------------------------------------------- 1 | {NSBrowserAuxiliary="_field1"@"NSMutableArray""_field2"@"_NSBrowserScrollView""_field3"@"NSClipView""_field4"@"_NSBrowserColumnScrollHelper""_field5"i"_field6"i"_field7"@"NSMatrix""_field8"@"NSEvent""_field9"f"_field10"@"NSMutableArray""_field11"i"_field12"i"_field13"@"NSString""_field14"{__BrFlags2="delegateShouldSizeColumnToWidth"b1"delegateSizeToFitWidtOfColumn"b1"shouldAnimateColumnScrolling"b1"tilingDisabled"b1"setPathOptimizationOn"b1"readingSavedColumns"b1"recomputeExistingColumnPositions"b1"waitingToSendDoubleActionAtEndOfScroll"b1"waitingToSendSingleActionAtEndOfScroll"b1"waitingToSendConfigChangeNotificationAtEndOfScroll"b1"compatContinuousScrollingCapable"b1"compatContinuousScrollingCapableSet"b1"forceSynchronizedScrollingAnimation"b1"useCustomBorderType"b1"customBorderType"b3"animateColumnScrollingForAnyEvent"b1"reserved"b14}} 2 | -------------------------------------------------------------------------------- /UnitTests.old/shud13-out.txt: -------------------------------------------------------------------------------- 1 | struct NSBrowserAuxiliary { 2 | NSMutableArray *_field1; 3 | _NSBrowserScrollView *_field2; 4 | NSClipView *_field3; 5 | _NSBrowserColumnScrollHelper *_field4; 6 | int _field5; 7 | int _field6; 8 | NSMatrix *_field7; 9 | NSEvent *_field8; 10 | float _field9; 11 | NSMutableArray *_field10; 12 | int _field11; 13 | int _field12; 14 | NSString *_field13; 15 | struct __BrFlags2 _field14; 16 | }; 17 | 18 | struct __BrFlags2 { 19 | unsigned int delegateShouldSizeColumnToWidth:1; 20 | unsigned int delegateSizeToFitWidtOfColumn:1; 21 | unsigned int shouldAnimateColumnScrolling:1; 22 | unsigned int tilingDisabled:1; 23 | unsigned int setPathOptimizationOn:1; 24 | unsigned int readingSavedColumns:1; 25 | unsigned int recomputeExistingColumnPositions:1; 26 | unsigned int waitingToSendDoubleActionAtEndOfScroll:1; 27 | unsigned int waitingToSendSingleActionAtEndOfScroll:1; 28 | unsigned int waitingToSendConfigChangeNotificationAtEndOfScroll:1; 29 | unsigned int compatContinuousScrollingCapable:1; 30 | unsigned int compatContinuousScrollingCapableSet:1; 31 | unsigned int forceSynchronizedScrollingAnimation:1; 32 | unsigned int useCustomBorderType:1; 33 | unsigned int customBorderType:3; 34 | unsigned int animateColumnScrollingForAnyEvent:1; 35 | unsigned int reserved:14; 36 | }; 37 | 38 | struct NSBrowserAuxiliary var; 39 | -------------------------------------------------------------------------------- /UnitTests.old/shud14-in.txt: -------------------------------------------------------------------------------- 1 | // This is a type from iPhoto 5 that caused problems. 2 | ^{IPAlbumList=^^?{vector >={?={?=^@^@^@}}}{_opaque_pthread_mutex_t=l[40c]}} 3 | -------------------------------------------------------------------------------- /UnitTests.old/shud14-out.txt: -------------------------------------------------------------------------------- 1 | struct IPAlbumList { 2 | void **; 3 | struct vector>; 4 | struct _opaque_pthread_mutex_t; 5 | }; 6 | 7 | struct _opaque_pthread_mutex_t { 8 | long; 9 | char [40]; 10 | }; 11 | 12 | struct vector> { 13 | struct { 14 | struct { 15 | id *; 16 | id *; 17 | id *; 18 | }; 19 | }; 20 | }; 21 | 22 | struct IPAlbumList *var; 23 | -------------------------------------------------------------------------------- /UnitTests.old/shud15-in.txt: -------------------------------------------------------------------------------- 1 | {my_struct1="field1"@"NSObject"} 2 | {my_struct2="field1"@"NSObject""field2"@} 3 | {my_struct3="field1"@"field2"@} 4 | {my_struct4=@"NSObject"} 5 | {my_struct5=@"NSObject"@"NSObject"} 6 | -------------------------------------------------------------------------------- /UnitTests.old/shud15-out.txt: -------------------------------------------------------------------------------- 1 | struct my_struct1 { 2 | NSObject *field1; 3 | }; 4 | 5 | struct my_struct2 { 6 | NSObject *field1; 7 | id field2; 8 | }; 9 | 10 | struct my_struct3 { 11 | id field1; 12 | id field2; 13 | }; 14 | 15 | struct my_struct4 { 16 | NSObject *; 17 | }; 18 | 19 | struct my_struct5 { 20 | NSObject *; 21 | NSObject *; 22 | }; 23 | 24 | struct my_struct1 var; 25 | struct my_struct2 var; 26 | struct my_struct3 var; 27 | struct my_struct4 var; 28 | struct my_struct5 var; 29 | -------------------------------------------------------------------------------- /UnitTests.old/shud16-in.txt: -------------------------------------------------------------------------------- 1 | // TextMate 1.5.4 has structures like... "storage""stack"{etc} -- two quoted strings next to each other. 2 | // It looks like this is a problem with the name rather than a problem with missing types -- when I compared 3 | // it to a case that didn't have names the types matched up perfectly. 4 | {my_struct1="storage""stack"i} 5 | -------------------------------------------------------------------------------- /UnitTests.old/shud16-out.txt: -------------------------------------------------------------------------------- 1 | struct my_struct1 { 2 | int storage__stack; 3 | }; 4 | 5 | struct my_struct1 var; 6 | -------------------------------------------------------------------------------- /UnitTests.old/var-001.txt: -------------------------------------------------------------------------------- 1 | // Test a pointer to no type in a structure. 2 | // This is an excerpt from the _topSitesViewController ivar of BrowserWebView in Safari 4.0 on Mac OS X 10.5. 3 | 4 | var1 5 | {?="__pfn"^"__delta"i} 6 | 7 | // Similar to the case above, but what happens if it occurs as the last member of the structure? 8 | 9 | var2 10 | {?="__pfn"^} 11 | 12 | // Combination of the first two cases. Order reversed from first case. 13 | 14 | var3 15 | {?="__delta"i"__pfn"^} 16 | 17 | // Same as the three tests above, but for unions. 18 | 19 | var4 20 | (?="__pfn"^"__delta"i) 21 | 22 | var5 23 | (?="__pfn"^) 24 | 25 | var6 26 | (?="__delta"i"__pfn"^) 27 | 28 | -------------------------------------------------------------------------------- /UnitTests.old/var-002.txt: -------------------------------------------------------------------------------- 1 | // This is an excerpt from the _topSitesViewController ivar of BrowserWebView in Safari 4.0 on Mac OS X 10.5. 2 | 3 | var1 4 | {STimer="_vptr$STimerBase"^^?"m_ID"I"m_isRepeating"B"m_object"^{TopSitesViewController}"m_function"{?="__pfn"^"__delta"i}} 5 | -------------------------------------------------------------------------------- /UnitTests.old/var-003.txt: -------------------------------------------------------------------------------- 1 | // This is the full definition of the _topSitesViewController ivar of BrowserWebView in Safari 4.0 on Mac OS X 10.5. 2 | 3 | _topSitesViewController 4 | ^{TopSitesViewController=^^?@"BrowserWebView"i^{TopSitesViewLayer}BII{SNotifier="_vptr$SNotificationObserver"^^?"m_notifiedObject"^{TopSitesViewController}"m_notifications"{HashMap,std::mem_fun1_t,WTF::PairHash,WTF::HashTraits >,WTF::HashTraits > >="m_impl"{HashTable,std::pair, std::mem_fun1_t >,WTF::PairFirstExtractor, std::mem_fun1_t > >,WTF::PairHash,WTF::PairHashTraits >, WTF::HashTraits > >,WTF::HashTraits > >="m_table"^{pair,std::mem_fun1_t >}"m_tableSize"i"m_tableSizeMask"i"m_keyCount"i"m_deletedCount"i}}}{STimer="_vptr$STimerBase"^^?"m_ID"I"m_isRepeating"B"m_object"^{TopSitesViewController}"m_function"{?="__pfn"^"__delta"i}}BBB{STimer="_vptr$STimerBase"^^?"m_ID"I"m_isRepeating"B"m_object"^{TopSitesViewController}"m_function"{?="__pfn"^"__delta"i}}{RefPtr="m_ptr"^{TopSite}}BB{STimer="_vptr$STimerBase"^^?"m_ID"I"m_isRepeating"B"m_object"^{TopSitesViewController}"m_function"{?="__pfn"^"__delta"i}}d{SString="m_cfObject"{RetainPtr="m_ptr"^{__CFString}}}BII{RetainPtr="m_ptr"^{CGImage}}} 5 | -------------------------------------------------------------------------------- /UnitTests.old/var-004.txt: -------------------------------------------------------------------------------- 1 | var 1 2 | {RetainPtr=^{__CFString}} 3 | 4 | var 5 | {My::List} 6 | 7 | var 8 | {My::List} 9 | 10 | var 11 | {My::List} 12 | 13 | var 14 | {My::List*,int>} 15 | 16 | // If it's still in the template mode, it adds any identifier after the > to the suffix; 17 | 18 | var 19 | {My::List*bob,int>} 20 | 21 | // And this should fail: 22 | var 23 | {My::List*} 24 | 25 | // Should this work or not? 26 | var 27 | {^My::List} 28 | 29 | -------------------------------------------------------------------------------- /UnitTests.old/var-005.txt: -------------------------------------------------------------------------------- 1 | // From Safari 4.0.2 on Mac OS X 10.5: 2 | 3 | var 4 | {pair, 0ul>*>} 5 | -------------------------------------------------------------------------------- /UnitTests/TestBlockSignature.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDType.h" 9 | #import "CDTypeName.h" 10 | 11 | @interface CDType (UnitTests) 12 | - (NSString *)blockSignatureString; 13 | @end 14 | 15 | @interface TestBlockSignature : XCTestCase 16 | @end 17 | 18 | @implementation TestBlockSignature 19 | 20 | - (void)testZeroArguments; 21 | { 22 | NSMutableArray *types = [NSMutableArray new]; 23 | [types addObject:[[CDType alloc] initSimpleType:'v']]; 24 | [types addObject:[[CDType alloc] initBlockTypeWithTypes:nil]]; 25 | CDType *blockType = [[CDType alloc] initBlockTypeWithTypes:types]; 26 | NSString *blockSignatureString = [blockType blockSignatureString]; 27 | XCTAssertEqualObjects(blockSignatureString, @"void (^)(void)", @""); 28 | } 29 | 30 | - (void)testOneArgument; 31 | { 32 | NSMutableArray *types = [NSMutableArray new]; 33 | [types addObject:[[CDType alloc] initSimpleType:'v']]; 34 | [types addObject:[[CDType alloc] initBlockTypeWithTypes:nil]]; 35 | CDTypeName *typeName = [CDTypeName new]; 36 | typeName.name = @"NSData"; 37 | [types addObject:[[CDType alloc] initIDType:typeName]]; 38 | CDType *blockType = [[CDType alloc] initBlockTypeWithTypes:types]; 39 | NSString *blockSignatureString = [blockType blockSignatureString]; 40 | XCTAssertEqualObjects(blockSignatureString, @"void (^)(NSData *)", @""); 41 | } 42 | 43 | - (void)testTwoArguments; 44 | { 45 | NSMutableArray *types = [NSMutableArray new]; 46 | [types addObject:[[CDType alloc] initSimpleType:'v']]; 47 | [types addObject:[[CDType alloc] initBlockTypeWithTypes:nil]]; 48 | [types addObject:[[CDType alloc] initIDType:nil]]; 49 | CDTypeName *typeName = [CDTypeName new]; 50 | typeName.name = @"NSError"; 51 | [types addObject:[[CDType alloc] initIDType:typeName]]; 52 | CDType *blockType = [[CDType alloc] initBlockTypeWithTypes:types]; 53 | NSString *blockSignatureString = [blockType blockSignatureString]; 54 | XCTAssertEqualObjects(blockSignatureString, @"void (^)(id, NSError *)", @""); 55 | } 56 | 57 | - (void)testBlockArgument; 58 | { 59 | NSMutableArray *types = [NSMutableArray new]; 60 | [types addObject:[[CDType alloc] initSimpleType:'v']]; 61 | [types addObject:[[CDType alloc] initBlockTypeWithTypes:nil]]; 62 | [types addObject:[[CDType alloc] initBlockTypeWithTypes:[types copy]]]; 63 | CDType *blockType = [[CDType alloc] initBlockTypeWithTypes:types]; 64 | NSString *blockSignatureString = [blockType blockSignatureString]; 65 | XCTAssertEqualObjects(blockSignatureString, @"void (^)(void (^)(void))", @""); 66 | } 67 | 68 | - (void)testBOOLArgument; 69 | { 70 | NSMutableArray *types = [NSMutableArray new]; 71 | [types addObject:[[CDType alloc] initSimpleType:'v']]; 72 | [types addObject:[[CDType alloc] initBlockTypeWithTypes:nil]]; 73 | [types addObject:[[CDType alloc] initSimpleType:'c']]; 74 | CDType *blockType = [[CDType alloc] initBlockTypeWithTypes:types]; 75 | NSString *blockSignatureString = [blockType blockSignatureString]; 76 | XCTAssertEqualObjects(blockSignatureString, @"void (^)(BOOL)", @""); 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /UnitTests/TestCDArchFromName.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFile.h" 9 | 10 | @interface TestCDArchFromName : XCTestCase 11 | @end 12 | 13 | @implementation TestCDArchFromName 14 | 15 | - (void)setUp; 16 | { 17 | [super setUp]; 18 | 19 | // Set-up code here. 20 | } 21 | 22 | - (void)tearDown; 23 | { 24 | // Tear-down code here. 25 | 26 | [super tearDown]; 27 | } 28 | 29 | #pragma mark - ARM 30 | 31 | - (void)test_armv6; 32 | { 33 | CDArch arch = CDArchFromName(@"armv6"); 34 | XCTAssertEqual(arch.cputype, CPU_TYPE_ARM, @"The cputype for 'armv6' should be ARM"); 35 | XCTAssertEqual(arch.cpusubtype, CPU_SUBTYPE_ARM_V6, @"The cpusubtype for 'armv6' should be ARM_V6"); 36 | } 37 | 38 | - (void)test_armv7; 39 | { 40 | CDArch arch = CDArchFromName(@"armv7"); 41 | XCTAssertEqual(arch.cputype, CPU_TYPE_ARM, @"The cputype for 'armv7' should be ARM"); 42 | XCTAssertEqual(arch.cpusubtype, CPU_SUBTYPE_ARM_V7, @"The cpusubtype for 'armv7' should be ARM_V7"); 43 | } 44 | 45 | - (void)test_armv7s; 46 | { 47 | CDArch arch = CDArchFromName(@"armv7s"); 48 | XCTAssertEqual(arch.cputype, CPU_TYPE_ARM, @"The cputype for 'armv7s' should be ARM"); 49 | XCTAssertEqual(arch.cpusubtype, 11, @"The cpusubtype for 'armv7s' should be 11"); 50 | } 51 | 52 | - (void)test_arm64; 53 | { 54 | CDArch arch = CDArchFromName(@"arm64"); 55 | XCTAssertEqual(arch.cputype, CPU_TYPE_ARM | CPU_ARCH_ABI64, @"The cputype for 'arm64' should be ARM with 64-bit mask"); 56 | XCTAssertEqual(arch.cpusubtype, CPU_SUBTYPE_ARM_ALL, @"The cpusubtype for 'arm64' should be CPU_SUBTYPE_ARM_ALL"); 57 | } 58 | 59 | #pragma mark - Intel x86 60 | 61 | - (void)test_i386; 62 | { 63 | CDArch arch = CDArchFromName(@"i386"); 64 | XCTAssertEqual(arch.cputype, CPU_TYPE_X86, @"The cputype for 'i386' should be X86"); 65 | XCTAssertEqual(arch.cpusubtype, CPU_SUBTYPE_386, @"The cpusubtype for 'i386' should be 386"); 66 | } 67 | 68 | - (void)test_x86_64; 69 | { 70 | CDArch arch = CDArchFromName(@"x86_64"); 71 | XCTAssertEqual(arch.cputype, CPU_TYPE_X86_64, @"The cputype for 'x86_64' should be X86_64"); 72 | XCTAssertEqual(arch.cpusubtype, CPU_SUBTYPE_386, @"The cpusubtype for 'x86_64' should be 386"); 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /UnitTests/TestCDArchUses64BitABI.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFile.h" 9 | 10 | @interface TestCDArchUses64BitABI : XCTestCase 11 | @end 12 | 13 | @implementation TestCDArchUses64BitABI 14 | 15 | - (void)setUp; 16 | { 17 | [super setUp]; 18 | 19 | // Set-up code here. 20 | } 21 | 22 | - (void)tearDown; 23 | { 24 | // Tear-down code here. 25 | 26 | [super tearDown]; 27 | } 28 | 29 | #pragma mark - Intel x86 30 | 31 | - (void)test_i386; 32 | { 33 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 34 | XCTAssertFalse(CDArchUses64BitABI(arch), @"i386 does not use 64 bit ABI"); 35 | } 36 | 37 | - (void)test_x86_64; 38 | { 39 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 40 | XCTAssertTrue(CDArchUses64BitABI(arch), @"x86_64 uses 64 bit ABI"); 41 | } 42 | 43 | - (void)test_x86_64_lib64; 44 | { 45 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 | CPU_SUBTYPE_LIB64 }; 46 | XCTAssertTrue(CDArchUses64BitABI(arch), @"x86_64 (with LIB64 capability bit) uses 64 bit ABI"); 47 | } 48 | 49 | - (void)test_x86_64_plusOtherCapablity 50 | { 51 | CDArch arch = { CPU_TYPE_X86_64 | 0x40000000, CPU_SUBTYPE_386 }; 52 | XCTAssertTrue(CDArchUses64BitABI(arch), @"x86_64 (with other capability bit) uses 64 bit ABI"); 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /UnitTests/TestCDNameForCPUType.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFile.h" 9 | 10 | @interface TestCDNameForCPUType : XCTestCase 11 | @end 12 | 13 | @implementation TestCDNameForCPUType 14 | 15 | - (void)setUp; 16 | { 17 | [super setUp]; 18 | 19 | // Set-up code here. 20 | } 21 | 22 | - (void)tearDown; 23 | { 24 | // Tear-down code here. 25 | 26 | [super tearDown]; 27 | } 28 | 29 | #pragma mark - ARM 30 | 31 | - (void)test_armv6; 32 | { 33 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6), @"armv6", @"The name for ARM subtype CPU_SUBTYPE_ARM_V6 should be 'armv6'"); 34 | } 35 | 36 | - (void)test_armv7; 37 | { 38 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7), @"armv7", @"The name for ARM subtype CPU_SUBTYPE_ARM_V7 should be 'armv7'"); 39 | } 40 | 41 | - (void)test_armv7s; 42 | { 43 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_ARM, 11), @"armv7s", @"The name for ARM subtype 11 should be 'armv7s'"); 44 | } 45 | 46 | - (void)test_arm64; 47 | { 48 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_ARM | CPU_ARCH_ABI64, CPU_SUBTYPE_ARM_ALL), @"arm64", @"The name for ARM 64-bit subtype CPU_SUBTYPE_ARM_ALL should be 'arm64'"); 49 | } 50 | 51 | #pragma mark - Intel x86 52 | 53 | - (void)test_i386; 54 | { 55 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_X86, CPU_SUBTYPE_386), @"i386", @"The name for X86 subtype CPU_SUBTYPE_386 should be 'i386'"); 56 | } 57 | 58 | - (void)test_x86_64; 59 | { 60 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_X86_64, CPU_SUBTYPE_386), @"x86_64", @"The name for X86_64 subtype CPU_SUBTYPE_386 should be 'x86_64'"); 61 | } 62 | 63 | - (void)test_x86_64_lib64; 64 | { 65 | XCTAssertEqualObjects(CDNameForCPUType(CPU_TYPE_X86_64, CPU_SUBTYPE_386|CPU_SUBTYPE_LIB64), @"x86_64", @"The name for X86_64 subtype CPU_SUBTYPE_386 with capability bits should be 'x86_64'"); 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /UnitTests/TestFatFile_Intel32_64.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFatArch.h" 9 | #import "CDFatFile.h" 10 | #import "CDMachOFile.h" 11 | 12 | @interface TestFatFile_Intel32_64 : XCTestCase 13 | @end 14 | 15 | @implementation TestFatFile_Intel32_64 16 | { 17 | CDFatFile *_fatFile; 18 | CDFatArch *_arch_i386; 19 | CDFatArch *_arch_x86_64; 20 | CDMachOFile *_macho_i386; 21 | CDMachOFile *_macho_x86_64; 22 | } 23 | 24 | - (void)setUp; 25 | { 26 | [super setUp]; 27 | 28 | // Set-up code here. 29 | _fatFile = [[CDFatFile alloc] init]; 30 | 31 | _macho_i386 = [[CDMachOFile alloc] init]; 32 | _macho_i386.cputype = CPU_TYPE_X86; 33 | _macho_i386.cpusubtype = CPU_SUBTYPE_386; 34 | 35 | _arch_i386 = [[CDFatArch alloc] initWithMachOFile:_macho_i386]; 36 | [_fatFile addArchitecture:_arch_i386]; 37 | 38 | _macho_x86_64 = [[CDMachOFile alloc] init]; 39 | _macho_x86_64.cputype = CPU_TYPE_X86_64; 40 | _macho_x86_64.cpusubtype = CPU_SUBTYPE_386; 41 | 42 | _arch_x86_64 = [[CDFatArch alloc] initWithMachOFile:_macho_x86_64]; 43 | [_fatFile addArchitecture:_arch_x86_64]; 44 | } 45 | 46 | - (void)tearDown; 47 | { 48 | // Tear-down code here. 49 | _fatFile = nil; 50 | _arch_i386 = nil; 51 | _arch_x86_64 = nil; 52 | _macho_i386 = nil; 53 | _macho_x86_64 = nil; 54 | 55 | [super tearDown]; 56 | } 57 | 58 | #pragma mark - 59 | 60 | - (void)test_bestMatchIntel64; 61 | { 62 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 63 | 64 | BOOL result = [_fatFile bestMatchForArch:&arch]; 65 | XCTAssertTrue(result, @"Didn't find a best match for x86_64"); 66 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86_64, @"Best match cputype should be CPU_TYPE_X86_64"); 67 | XCTAssertTrue(arch.cpusubtype == CPU_SUBTYPE_386, @"Best match cpusubtype should be CPU_SUBTYPE_386"); 68 | } 69 | 70 | #if 0 71 | // We don't build 32-bit any more, so this test case shouldn't come up. 72 | - (void)test_bestMatchIntel32; 73 | { 74 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 75 | 76 | BOOL result = [_intel_32_64 bestMatchForArch:&arch]; 77 | XCTAssertTrue(result, @"Didn't find a best match for i386"); 78 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86, @"Best match cputype should be CPU_TYPE_X86"); 79 | XCTAssertTrue(arch.cpusubtype == CPU_SUBTYPE_386, @"Best match cpusubtype should be CPU_SUBTYPE_386"); 80 | } 81 | #endif 82 | 83 | - (void)test_machOFileWithArch_x86_64; 84 | { 85 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 86 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 87 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 88 | XCTAssertEqual(machOFile, _macho_x86_64, @"Didn't find correct Mach-O file"); 89 | } 90 | 91 | - (void)test_machOFileWithArch_i386; 92 | { 93 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 94 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 95 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil"); 96 | XCTAssertEqual(machOFile, _macho_i386, @"Didn't find correct Mach-O file"); 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /UnitTests/TestFatFile_Intel32_64_lib64.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFatArch.h" 9 | #import "CDFatFile.h" 10 | #import "CDMachOFile.h" 11 | 12 | @interface TestFatFile_Intel32_64_lib64 : XCTestCase 13 | @end 14 | 15 | @implementation TestFatFile_Intel32_64_lib64 16 | { 17 | CDFatFile *_fatFile; 18 | CDFatArch *_arch_i386; 19 | CDFatArch *_arch_x86_64; 20 | CDMachOFile *_macho_i386; 21 | CDMachOFile *_macho_x86_64; 22 | } 23 | 24 | - (void)setUp; 25 | { 26 | [super setUp]; 27 | 28 | // Set-up code here. 29 | _fatFile = [[CDFatFile alloc] init]; 30 | 31 | _macho_i386 = [[CDMachOFile alloc] init]; 32 | _macho_i386.cputype = CPU_TYPE_X86; 33 | _macho_i386.cpusubtype = CPU_SUBTYPE_386; 34 | 35 | _arch_i386 = [[CDFatArch alloc] initWithMachOFile:_macho_i386]; 36 | [_fatFile addArchitecture:_arch_i386]; 37 | 38 | _macho_x86_64 = [[CDMachOFile alloc] init]; 39 | _macho_x86_64.cputype = CPU_TYPE_X86_64; 40 | _macho_x86_64.cpusubtype = CPU_SUBTYPE_386 | CPU_SUBTYPE_LIB64; 41 | 42 | _arch_x86_64 = [[CDFatArch alloc] initWithMachOFile:_macho_x86_64]; 43 | [_fatFile addArchitecture:_arch_x86_64]; 44 | } 45 | 46 | - (void)tearDown; 47 | { 48 | // Tear-down code here. 49 | _fatFile = nil; 50 | _arch_i386 = nil; 51 | _arch_x86_64 = nil; 52 | _macho_i386 = nil; 53 | _macho_x86_64 = nil; 54 | 55 | [super tearDown]; 56 | } 57 | 58 | #pragma mark - 59 | 60 | - (void)test_bestMatchIntel64; 61 | { 62 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 63 | 64 | BOOL result = [_fatFile bestMatchForArch:&arch]; 65 | XCTAssertTrue(result, @"Didn't find a best match for x86_64"); 66 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86_64, @"Best match cputype should be CPU_TYPE_X86_64"); 67 | XCTAssertTrue(arch.cpusubtype == (cpu_subtype_t)(CPU_SUBTYPE_386 | CPU_SUBTYPE_LIB64), @"Best match cpusubtype should be CPU_SUBTYPE_386"); 68 | } 69 | 70 | #if 0 71 | // We don't build 32-bit any more, so this test case shouldn't come up. 72 | - (void)test_bestMatchIntel32; 73 | { 74 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 75 | 76 | BOOL result = [_intel_32_64 bestMatchForArch:&arch]; 77 | XCTAssertTrue(result, @"Didn't find a best match for i386"); 78 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86, @"Best match cputype should be CPU_TYPE_X86"); 79 | XCTAssertTrue(arch.cpusubtype == CPU_SUBTYPE_386, @"Best match cpusubtype should be CPU_SUBTYPE_386"); 80 | } 81 | #endif 82 | 83 | - (void)test_machOFileWithArch_x86_64; 84 | { 85 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 86 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 87 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 88 | XCTAssertEqual(machOFile, _macho_x86_64, @"Didn't find correct Mach-O file"); 89 | } 90 | 91 | - (void)test_machOFileWithArch_i386; 92 | { 93 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 94 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 95 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil"); 96 | XCTAssertEqual(machOFile, _macho_i386, @"Didn't find correct Mach-O file"); 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /UnitTests/TestFatFile_Intel64_32.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFatArch.h" 9 | #import "CDFatFile.h" 10 | #import "CDMachOFile.h" 11 | 12 | @interface TestFatFile_Intel64_32 : XCTestCase 13 | @end 14 | 15 | @implementation TestFatFile_Intel64_32 16 | { 17 | CDFatFile *_fatFile; 18 | CDFatArch *_arch_i386; 19 | CDFatArch *_arch_x86_64; 20 | CDMachOFile *_macho_i386; 21 | CDMachOFile *_macho_x86_64; 22 | } 23 | 24 | - (void)setUp; 25 | { 26 | [super setUp]; 27 | 28 | // Set-up code here. 29 | _fatFile = [[CDFatFile alloc] init]; 30 | 31 | _macho_x86_64 = [[CDMachOFile alloc] init]; 32 | _macho_x86_64.cputype = CPU_TYPE_X86_64; 33 | _macho_x86_64.cpusubtype = CPU_SUBTYPE_386; 34 | 35 | _arch_x86_64 = [[CDFatArch alloc] initWithMachOFile:_macho_x86_64]; 36 | [_fatFile addArchitecture:_arch_x86_64]; 37 | 38 | _macho_i386 = [[CDMachOFile alloc] init]; 39 | _macho_i386.cputype = CPU_TYPE_X86; 40 | _macho_i386.cpusubtype = CPU_SUBTYPE_386; 41 | 42 | _arch_i386 = [[CDFatArch alloc] initWithMachOFile:_macho_i386]; 43 | [_fatFile addArchitecture:_arch_i386]; 44 | } 45 | 46 | - (void)tearDown; 47 | { 48 | // Tear-down code here. 49 | _fatFile = nil; 50 | _arch_i386 = nil; 51 | _arch_x86_64 = nil; 52 | _macho_i386 = nil; 53 | _macho_x86_64 = nil; 54 | 55 | [super tearDown]; 56 | } 57 | 58 | #pragma mark - 59 | 60 | - (void)test_bestMatchIntel64; 61 | { 62 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 63 | 64 | BOOL result = [_fatFile bestMatchForArch:&arch]; 65 | XCTAssertTrue(result, @"Didn't find a best match for x86_64"); 66 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86_64, @"Best match cputype should be CPU_TYPE_X86_64"); 67 | XCTAssertTrue(arch.cpusubtype == CPU_SUBTYPE_386, @"Best match cpusubtype should be CPU_SUBTYPE_386"); 68 | } 69 | 70 | #if 0 71 | // We don't build 32-bit any more, so this test case shouldn't come up. 72 | - (void)test_bestMatchIntel32; 73 | { 74 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 75 | 76 | BOOL result = [_intel_64_32 bestMatchForArch:&arch]; 77 | XCTAssertTrue(result, @"Didn't find a best match for i386"); 78 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86, @"Best match cputype should be CPU_TYPE_X86"); 79 | XCTAssertTrue(arch.cpusubtype == CPU_SUBTYPE_386, @"Best match cpusubtype should be CPU_SUBTYPE_386"); 80 | } 81 | #endif 82 | 83 | - (void)test_machOFileWithArch_x86_64; 84 | { 85 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 86 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 87 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 88 | XCTAssertEqual(machOFile, _macho_x86_64, @"Didn't find correct Mach-O file", NULL); 89 | } 90 | 91 | - (void)test_machOFileWithArch_i386; 92 | { 93 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 94 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 95 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 96 | XCTAssertEqual(machOFile, _macho_i386, @"Didn't find correct Mach-O file"); 97 | } 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /UnitTests/TestFatFile_armv7_v7s.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFatArch.h" 9 | #import "CDFatFile.h" 10 | #import "CDMachOFile.h" 11 | 12 | @interface TestFatFile_armv7_v7s : XCTestCase 13 | @end 14 | 15 | @implementation TestFatFile_armv7_v7s 16 | { 17 | CDFatFile *_fatFile; 18 | CDFatArch *_arch_v7; 19 | CDFatArch *_arch_v7s; 20 | CDMachOFile *_macho_v7; 21 | CDMachOFile *_macho_v7s; 22 | } 23 | 24 | - (void)setUp; 25 | { 26 | [super setUp]; 27 | 28 | // Set-up code here. 29 | _fatFile = [[CDFatFile alloc] init]; 30 | 31 | _macho_v7 = [[CDMachOFile alloc] init]; 32 | _macho_v7.cputype = CPU_TYPE_ARM; 33 | _macho_v7.cpusubtype = CPU_SUBTYPE_ARM_V7; 34 | 35 | _arch_v7 = [[CDFatArch alloc] initWithMachOFile:_macho_v7]; 36 | [_fatFile addArchitecture:_arch_v7]; 37 | 38 | _macho_v7s = [[CDMachOFile alloc] init]; 39 | _macho_v7s.cputype = CPU_TYPE_ARM; 40 | _macho_v7s.cpusubtype = 11; 41 | 42 | _arch_v7s = [[CDFatArch alloc] initWithMachOFile:_macho_v7s]; 43 | [_fatFile addArchitecture:_arch_v7s]; 44 | } 45 | 46 | - (void)tearDown; 47 | { 48 | // Tear-down code here. 49 | _fatFile = nil; 50 | _arch_v7 = nil; 51 | _arch_v7s = nil; 52 | _macho_v7 = nil; 53 | _macho_v7s = nil; 54 | 55 | [super tearDown]; 56 | } 57 | 58 | #pragma mark - 59 | 60 | - (void)test_machOFileWithArch_armv7; 61 | { 62 | CDArch arch = { CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7 }; 63 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 64 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 65 | XCTAssertEqual(machOFile, _macho_v7, @"Didn't find correct Mach-O file"); 66 | } 67 | 68 | - (void)test_machOFileWithArch_armv7s; 69 | { 70 | CDArch arch = { CPU_TYPE_ARM, 11 }; 71 | CDMachOFile *machOFile = [_fatFile machOFileWithArch:arch]; 72 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil"); 73 | XCTAssertEqual(machOFile, _macho_v7s, @"Didn't find correct Mach-O file"); 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /UnitTests/TestThinFile_Intel64.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFatArch.h" 9 | #import "CDFatFile.h" 10 | #import "CDMachOFile.h" 11 | 12 | @interface TestThinFile_Intel64 : XCTestCase 13 | @end 14 | 15 | @implementation TestThinFile_Intel64 16 | { 17 | CDMachOFile *_macho_x86_64; 18 | } 19 | 20 | - (void)setUp; 21 | { 22 | [super setUp]; 23 | 24 | // Set-up code here. 25 | _macho_x86_64 = [[CDMachOFile alloc] init]; 26 | _macho_x86_64.cputype = CPU_TYPE_X86_64; 27 | _macho_x86_64.cpusubtype = CPU_SUBTYPE_386; 28 | } 29 | 30 | - (void)tearDown; 31 | { 32 | // Tear-down code here. 33 | _macho_x86_64 = nil; 34 | 35 | [super tearDown]; 36 | } 37 | 38 | #pragma mark - 39 | 40 | - (void)test_bestMatchIntel64; 41 | { 42 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 43 | 44 | BOOL result = [_macho_x86_64 bestMatchForArch:&arch]; 45 | XCTAssertTrue(result, @"Didn't find a best match for x86_64"); 46 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86_64, @"Best match cputype should be CPU_TYPE_X86_64"); 47 | XCTAssertTrue(arch.cpusubtype == CPU_SUBTYPE_386, @"Best match cpusubtype should be CPU_SUBTYPE_386"); 48 | } 49 | 50 | - (void)test_machOFileWithArch_x86_64; 51 | { 52 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 53 | CDMachOFile *machOFile = [_macho_x86_64 machOFileWithArch:arch]; 54 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 55 | XCTAssertEqual(machOFile, _macho_x86_64, @"Didn't find correct Mach-O file", NULL); 56 | } 57 | 58 | - (void)test_machOFileWithArch_i386; 59 | { 60 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 61 | CDMachOFile *machOFile = [_macho_x86_64 machOFileWithArch:arch]; 62 | XCTAssertNil(machOFile, @"The Mach-O file should be nil", NULL); 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /UnitTests/TestThinFile_Intel64_lib64.m: -------------------------------------------------------------------------------- 1 | // -*- mode: ObjC -*- 2 | 3 | // This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. 4 | // Copyright (C) 1997-2019 Steve Nygard. 5 | 6 | #import 7 | 8 | #import "CDFatArch.h" 9 | #import "CDFatFile.h" 10 | #import "CDMachOFile.h" 11 | 12 | @interface TestThinFile_Intel64_lib64 : XCTestCase 13 | @end 14 | 15 | @implementation TestThinFile_Intel64_lib64 16 | { 17 | CDMachOFile *_macho_x86_64; 18 | } 19 | 20 | - (void)setUp; 21 | { 22 | [super setUp]; 23 | 24 | // Set-up code here. 25 | _macho_x86_64 = [[CDMachOFile alloc] init]; 26 | _macho_x86_64.cputype = CPU_TYPE_X86_64; 27 | _macho_x86_64.cpusubtype = CPU_SUBTYPE_386 | CPU_SUBTYPE_LIB64; // For example, /Applications/Utilities/Grab.app on 10.8 28 | } 29 | 30 | - (void)tearDown; 31 | { 32 | // Tear-down code here. 33 | _macho_x86_64 = nil; 34 | 35 | [super tearDown]; 36 | } 37 | 38 | #pragma mark - 39 | 40 | - (void)test_bestMatchIntel64; 41 | { 42 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 43 | 44 | BOOL result = [_macho_x86_64 bestMatchForArch:&arch]; 45 | XCTAssertTrue(result, @"Didn't find a best match for x86_64"); 46 | XCTAssertTrue(arch.cputype == CPU_TYPE_X86_64, @"Best match cputype should be CPU_TYPE_X86_64"); 47 | XCTAssertTrue(arch.cpusubtype == (cpu_subtype_t)(CPU_SUBTYPE_386 | CPU_SUBTYPE_LIB64), @"Best match cpusubtype should be CPU_SUBTYPE_386"); 48 | } 49 | 50 | - (void)test_machOFileWithArch_x86_64; 51 | { 52 | CDArch arch = { CPU_TYPE_X86_64, CPU_SUBTYPE_386 }; 53 | CDMachOFile *machOFile = [_macho_x86_64 machOFileWithArch:arch]; 54 | XCTAssertNotNil(machOFile, @"The Mach-O file shouldn't be nil", NULL); 55 | XCTAssertEqual(machOFile, _macho_x86_64, @"Didn't find correct Mach-O file", NULL); 56 | } 57 | 58 | - (void)test_machOFileWithArch_i386; 59 | { 60 | CDArch arch = { CPU_TYPE_X86, CPU_SUBTYPE_386 }; 61 | CDMachOFile *machOFile = [_macho_x86_64 machOFileWithArch:arch]; 62 | XCTAssertNil(machOFile, @"The Mach-O file should be nil", NULL); 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /UnitTests/UnitTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /UnitTests/UnitTests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /UnitTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /class-dump-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'class-dump' target in the 'class-dump' project. 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "CDExtensions.h" 8 | #define __cmd __PRETTY_FUNCTION__ 9 | #endif 10 | -------------------------------------------------------------------------------- /class-dump.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /class-dump.xcodeproj/project.xcworkspace/xcuserdata/nygard.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceUserSettings_BuildLocationStyle 6 | 0 7 | IDEWorkspaceUserSettings_BuildSubfolderNameStyle 8 | 0 9 | IDEWorkspaceUserSettings_DerivedDataLocationStyle 10 | 0 11 | IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IDEWorkspaceUserSettings_IssueFilterStyle 14 | 0 15 | IDEWorkspaceUserSettings_LiveSourceIssuesEnabled 16 | 17 | IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | IDEWorkspaceUserSettings_SnapshotLocationStyle 20 | 0 21 | 22 | 23 | -------------------------------------------------------------------------------- /class-dump.xcodeproj/xcuserdata/nygard.xcuserdatad/xcschemes/MachObjC.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 77 | 78 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /class-dump.xcodeproj/xcuserdata/nygard.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MachObjC.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | all.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | class-dump.xcscheme 18 | 19 | orderHint 20 | 2 21 | 22 | deprotect.xcscheme 23 | 24 | orderHint 25 | 3 26 | 27 | formatType.xcscheme 28 | 29 | orderHint 30 | 4 31 | 32 | 33 | SuppressBuildableAutocreation 34 | 35 | 011E483D1604DF3700722F8D 36 | 37 | primary 38 | 39 | 40 | 012FF1890CDB886C00F31E61 41 | 42 | primary 43 | 44 | 45 | 013182B00CDF6EE400EC5A2C 46 | 47 | primary 48 | 49 | 50 | 013D1EFA13A5A0F100BF0A67 51 | 52 | primary 53 | 54 | 55 | 013D1F1013A5AE5A00BF0A67 56 | 57 | primary 58 | 59 | 60 | 013E8CE814EA0285002BDB6D 61 | 62 | primary 63 | 64 | 65 | 013E8CEE14EA04E0002BDB6D 66 | 67 | primary 68 | 69 | 70 | 01549F710903BF88002FA8F1 71 | 72 | primary 73 | 74 | 75 | 0165B8B01827137D00CC647F 76 | 77 | primary 78 | 79 | 80 | 01A9A4BC0FF19B2F00475772 81 | 82 | primary 83 | 84 | 85 | 01A9A4C40FF19BAE00475772 86 | 87 | primary 88 | 89 | 90 | 01B02CFE13A5B0DC0047BC53 91 | 92 | primary 93 | 94 | 95 | 01B02D2E13A5B5D50047BC53 96 | 97 | primary 98 | 99 | 100 | 01EB825E13A590D9003EDE60 101 | 102 | primary 103 | 104 | 105 | 01F5238E1001D19A0006B272 106 | 107 | primary 108 | 109 | 110 | 01F524FF1001F3E60006B272 111 | 112 | primary 113 | 114 | 115 | 8DD76F960486AA7600D96B5E 116 | 117 | primary 118 | 119 | 120 | DAF6959411E62A4F009AF361 121 | 122 | primary 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /deprotect-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'deprotect' target in the 'deprotect' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "CDExtensions.h" 8 | #endif 9 | -------------------------------------------------------------------------------- /formatType-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'formatType' target in the 'formatType' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import "CDExtensions.h" 8 | #endif 9 | -------------------------------------------------------------------------------- /keys.txt: -------------------------------------------------------------------------------- 1 | APPNAME=class-dump 2 | SHORT_DESCRIPTION=a utility for examining the Objective-C segment of Mach-O files 3 | OWNER=Steve Nygard 4 | COPYRIGHT=Copyright (C) 1997-2019 Steve Nygard. 5 | --------------------------------------------------------------------------------