Skip to content

Commit

Permalink
-Added CDOCClassReference to wrap any of a CDOCClass, CDSymbol, or NS…
Browse files Browse the repository at this point in the history
…String (class name) and use that to infer the class name and whether or not the class is external

-Use that class instead of a weakly typed property for CDOCClass’s superClassRef and CDOCCategory’s classRef
  • Loading branch information
aricha committed Jan 7, 2014
1 parent 1e70fe5 commit 5f1e0e3
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 40 deletions.
13 changes: 7 additions & 6 deletions Source/CDClassFrameworkVisitor.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "CDSymbol.h"
#import "CDLCDylib.h"
#import "CDOCCategory.h"
#import "CDOCClassReference.h"

@interface CDClassFrameworkVisitor ()
@property (strong) NSString *frameworkName;
Expand Down Expand Up @@ -47,9 +48,9 @@ - (void)willVisitClass:(CDOCClass *)aClass;
[self addClassName:aClass.name referencedInFramework:self.frameworkName];

// We only need to add superclasses for external classes - classes defined in this binary will be visited on their own
id superClassRef = [aClass superClassRef];
if ([superClassRef isKindOfClass:[CDSymbol class]]) {
[self addClassForExternalSymbol:superClassRef];
CDOCClassReference *superClassRef = [aClass superClassRef];
if ([superClassRef isExternalClass] && superClassRef.classSymbol) {
[self addClassForExternalSymbol:superClassRef.classSymbol];
}
}

Expand All @@ -61,9 +62,9 @@ - (void)willVisitProtocol:(CDOCProtocol *)protocol

- (void)willVisitCategory:(CDOCCategory *)category
{
id classRef = [category classRef];
if ([classRef isKindOfClass:[CDSymbol class]]) {
[self addClassForExternalSymbol:classRef];
CDOCClassReference *classRef = [category classRef];
if ([classRef isExternalClass] && classRef.classSymbol) {
[self addClassForExternalSymbol:classRef.classSymbol];
}
}

Expand Down
4 changes: 3 additions & 1 deletion Source/CDOCCategory.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@

#import "CDOCProtocol.h"

@class CDOCClassReference;

@interface CDOCCategory : CDOCProtocol <CDTopologicalSort>

@property (strong) id classRef; // Can be CDOCClass, CDSymbol (for external classes), or NSString (for ObjC1 class refs)
@property (strong) CDOCClassReference *classRef;
@property (strong, readonly) NSString *className;

- (NSString *)methodSearchContext;
Expand Down
14 changes: 2 additions & 12 deletions Source/CDOCCategory.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#import "CDVisitor.h"
#import "CDVisitorPropertyState.h"
#import "CDOCClass.h"
#import "CDSymbol.h"
#import "CDOCClassReference.h"

@implementation CDOCCategory

Expand All @@ -25,17 +25,7 @@ - (NSString *)sortableName;

- (NSString *)className
{
if ([_classRef isKindOfClass:[CDOCClass class]]) {
return [(CDOCClass *)_classRef name];
} else if ([_classRef isKindOfClass:[CDSymbol class]]) {
NSString *name = [(CDSymbol *)_classRef name];
return [CDSymbol classNameFromSymbolName:name];
} else if ([_classRef isKindOfClass:[NSString class]]) {
return _classRef;
} else {
if (_classRef) NSLog(@"unknown category class instance %@", _classRef);
return nil;
}
return [_classRef className];
}

- (NSString *)methodSearchContext;
Expand Down
6 changes: 4 additions & 2 deletions Source/CDOCClass.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@

#import "CDTopologicalSortProtocol.h"

@class CDOCClassReference;

@interface CDOCClass : CDOCProtocol <CDTopologicalSort>

@property (strong) id superClassRef; // can be CDOCClass, CDSymbol (for external classes), or NSString (for ObjC1 class refs)
@property (strong, readonly) NSString *superClassName;
@property (strong) CDOCClassReference *superClassRef;
@property (copy, readonly) NSString *superClassName;
@property (strong) NSArray *instanceVariables;
@property (assign) BOOL isExported;

Expand Down
14 changes: 2 additions & 12 deletions Source/CDOCClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#import "CDTypeParser.h"
#import "CDVisitor.h"
#import "CDVisitorPropertyState.h"
#import "CDSymbol.h"
#import "CDOCClassReference.h"

@implementation CDOCClass
{
Expand Down Expand Up @@ -42,17 +42,7 @@ - (NSString *)description;

- (NSString *)superClassName
{
if ([_superClassRef isKindOfClass:[CDOCClass class]]) {
return [(CDOCClass *)_superClassRef name];
} else if ([_superClassRef isKindOfClass:[CDSymbol class]]) {
NSString *name = [(CDSymbol *)_superClassRef name];
return [CDSymbol classNameFromSymbolName:name];
} else if ([_superClassRef isKindOfClass:[NSString class]]) {
return _superClassRef;
} else {
if (_superClassRef) NSLog(@"unknown superclass instance %@", _superClassRef);
return nil;
}
return [_superClassRef className];
}

- (void)registerTypesWithObject:(CDTypeController *)typeController phase:(NSUInteger)phase;
Expand Down
27 changes: 27 additions & 0 deletions Source/CDOCClassReference.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// -*- mode: ObjC -*-

// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
// Copyright (C) 1997-1998, 2000-2001, 2004-2013 Steve Nygard.

#import <Foundation/Foundation.h>

@class CDOCClass, CDSymbol;

/*!
* CDOCClassReference acts as a proxy object to a class that may be external. It can thus be repesented
* as one of: a \c CDOCClass object (for internal classes), a \c CDSymbol object (for external classes),
* or an \c NSString of the class name (for ObjC1 compatibility). The class name can then be inferred from
* any of these representations.
*/
@interface CDOCClassReference : NSObject

@property (strong) CDOCClass *classObject;
@property (strong) CDSymbol *classSymbol;
@property (nonatomic, copy) NSString *className; // inferred from classObject / classSymbol if not set directly
@property (nonatomic, readonly, getter = isExternalClass) BOOL externalClass;

- (instancetype)initWithClassObject:(CDOCClass *)classObject;
- (instancetype)initWithClassSymbol:(CDSymbol *)symbol;
- (instancetype)initWithClassName:(NSString *)className;

@end
53 changes: 53 additions & 0 deletions Source/CDOCClassReference.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// -*- mode: ObjC -*-

// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
// Copyright (C) 1997-1998, 2000-2001, 2004-2013 Steve Nygard.

#import "CDOCClassReference.h"
#import "CDOCClass.h"
#import "CDSymbol.h"

@implementation CDOCClassReference

- (instancetype)initWithClassSymbol:(CDSymbol *)symbol
{
if ((self = [super init])) {
_classSymbol = symbol;
}
return self;
}

- (instancetype)initWithClassObject:(CDOCClass *)classObject
{
if ((self = [super init])) {
_classObject = classObject;
}
return self;
}

- (instancetype)initWithClassName:(NSString *)className
{
if ((self = [super init])) {
_className = [className copy];
}
return self;
}

- (NSString *)className
{
if (_className)
return _className;
else if (_classObject)
return [_classObject name];
else if (_classSymbol)
return [CDSymbol classNameFromSymbolName:[_classSymbol name]];
else
return nil;
}

- (BOOL)isExternalClass
{
return (!_classObject && (!_classSymbol || [_classSymbol isExternal]));
}

@end
6 changes: 3 additions & 3 deletions Source/CDObjectiveC1Processor.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#import "CDLCSegment32.h"
#import "CDVisitor.h"
#import "CDProtocolUniquer.h"

#import "CDOCClassReference.h"

#import "CDSection.h"
#import "CDLCSegment.h"
Expand Down Expand Up @@ -262,7 +262,7 @@ - (CDOCClass *)processClassDefinitionAtAddress:(uint32_t)address;
aClass.name = className;

// TODO: can we extract more than just the string from here?
aClass.superClassRef = [self.machOFile stringAtAddress:objcClass.super_class];
aClass.superClassRef = [[CDOCClassReference alloc] initWithClassName:[self.machOFile stringAtAddress:objcClass.super_class]];

// Process ivars
if (objcClass.ivars != 0) {
Expand Down Expand Up @@ -426,7 +426,7 @@ - (CDOCCategory *)processCategoryDefinitionAtAddress:(uint32_t)address;
category.name = name;

// TODO: can we extract more than just the string from here?
category.classRef = [self.machOFile stringAtAddress:objcCategory.class_name];
category.classRef = [[CDOCClassReference alloc] initWithClassName:[self.machOFile stringAtAddress:objcCategory.class_name]];

for (CDOCMethod *method in [self processMethodsAtAddress:objcCategory.methods])
[category addInstanceMethod:method];
Expand Down
9 changes: 5 additions & 4 deletions Source/CDObjectiveC2Processor.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#import "CDOCProperty.h"
#import "cd_objc2.h"
#import "CDProtocolUniquer.h"
#import "CDOCClassReference.h"

@implementation CDObjectiveC2Processor
{
Expand Down Expand Up @@ -183,13 +184,13 @@ - (CDOCCategory *)loadCategoryAtAddress:(uint64_t)address;
//NSLog(@"category: got external class name (1): %@", [aClass className]);
} else if (objc2Category.class != 0) {
CDOCClass *aClass = [self classWithAddress:objc2Category.class];
[category setClassRef:aClass];
category.classRef = [[CDOCClassReference alloc] initWithClassObject:aClass];
}

if (externalClassName) {
CDSymbol *classSymbol = [[self.machOFile symbolTable] symbolForExternalClassName:externalClassName];
if (classSymbol)
[category setClassRef:classSymbol];
category.classRef = [[CDOCClassReference alloc] initWithClassSymbol:classSymbol];
}
}

Expand Down Expand Up @@ -272,13 +273,13 @@ - (CDOCClass *)loadClassAtAddress:(uint64_t)address;
//NSLog(@"class: got external class name (1): %@", [aClass superClassName]);
} else if (objc2Class.superclass != 0) {
CDOCClass *sc = [self loadClassAtAddress:objc2Class.superclass];
aClass.superClassRef = sc;
aClass.superClassRef = [[CDOCClassReference alloc] initWithClassObject:sc];
}

if (superClassName) {
CDSymbol *superClassSymbol = [[self.machOFile symbolTable] symbolForExternalClassName:superClassName];
if (superClassSymbol)
aClass.superClassRef = superClassSymbol;
aClass.superClassRef = [[CDOCClassReference alloc] initWithClassSymbol:superClassSymbol];
}
}

Expand Down
8 changes: 8 additions & 0 deletions class-dump.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@
01B02D2D13A5B57E0047BC53 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 013D1F0B13A5ADC300BF0A67 /* libcrypto.dylib */; };
01B02D3A13A5B72B0047BC53 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 013D1F0B13A5ADC300BF0A67 /* libcrypto.dylib */; };
01EB826413A590D9003EDE60 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01EB826313A590D9003EDE60 /* Foundation.framework */; };
0D288C10187BC2EE0026E2A0 /* CDOCClassReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 0D288C0E187BC2EE0026E2A0 /* CDOCClassReference.h */; };
0D288C11187BC2EE0026E2A0 /* CDOCClassReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D288C0F187BC2EE0026E2A0 /* CDOCClassReference.m */; };
C270B5C616C54AD6006CA75D /* ULEB128.m in Sources */ = {isa = PBXBuildFile; fileRef = C270B5C516C54AD5006CA75D /* ULEB128.m */; };
C270B5C816C54B0C006CA75D /* ULEB128.h in Headers */ = {isa = PBXBuildFile; fileRef = C270B5C716C54B0A006CA75D /* ULEB128.h */; };
DA7533B213AA587A003BE32C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01EB826313A590D9003EDE60 /* Foundation.framework */; };
Expand Down Expand Up @@ -420,6 +422,8 @@
01EB831E13A591D8003EDE60 /* CDVisitor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVisitor.m; path = Source/CDVisitor.m; sourceTree = SOURCE_ROOT; };
01EB831F13A591D8003EDE60 /* CDVisitorPropertyState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDVisitorPropertyState.h; path = Source/CDVisitorPropertyState.h; sourceTree = SOURCE_ROOT; };
01EB832013A591D8003EDE60 /* CDVisitorPropertyState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDVisitorPropertyState.m; path = Source/CDVisitorPropertyState.m; sourceTree = SOURCE_ROOT; };
0D288C0E187BC2EE0026E2A0 /* CDOCClassReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDOCClassReference.h; path = Source/CDOCClassReference.h; sourceTree = "<group>"; };
0D288C0F187BC2EE0026E2A0 /* CDOCClassReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDOCClassReference.m; path = Source/CDOCClassReference.m; sourceTree = "<group>"; };
C270B5C516C54AD5006CA75D /* ULEB128.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ULEB128.m; path = Source/ULEB128.m; sourceTree = "<group>"; };
C270B5C716C54B0A006CA75D /* ULEB128.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ULEB128.h; path = Source/ULEB128.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand Down Expand Up @@ -789,6 +793,8 @@
01EB836913A593C7003EDE60 /* Objective-C */ = {
isa = PBXGroup;
children = (
0D288C0E187BC2EE0026E2A0 /* CDOCClassReference.h */,
0D288C0F187BC2EE0026E2A0 /* CDOCClassReference.m */,
01EB831F13A591D8003EDE60 /* CDVisitorPropertyState.h */,
01EB832013A591D8003EDE60 /* CDVisitorPropertyState.m */,
01EB82E913A591D8003EDE60 /* CDOCCategory.h */,
Expand Down Expand Up @@ -839,6 +845,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
0D288C10187BC2EE0026E2A0 /* CDOCClassReference.h in Headers */,
0168C98713E4AB3200926EC3 /* CDLCFunctionStarts.h in Headers */,
018BFD4214F65DB600190F07 /* CDExtensions.h in Headers */,
0179B9E614F2025E00EC98F7 /* CDLCMain.h in Headers */,
Expand Down Expand Up @@ -1044,6 +1051,7 @@
013D1F4713A5AEA100BF0A67 /* CDOCCategory.m in Sources */,
013D1F4813A5AEA100BF0A67 /* CDOCClass.m in Sources */,
013D1F4913A5AEA100BF0A67 /* CDOCInstanceVariable.m in Sources */,
0D288C11187BC2EE0026E2A0 /* CDOCClassReference.m in Sources */,
013D1F4A13A5AEA100BF0A67 /* CDOCMethod.m in Sources */,
013D1F4B13A5AEA100BF0A67 /* CDOCModule.m in Sources */,
013D1F4C13A5AEA100BF0A67 /* CDOCProperty.m in Sources */,
Expand Down

0 comments on commit 5f1e0e3

Please sign in to comment.