mirror of
https://github.com/darlinghq/class-dump.git
synced 2025-02-11 23:07:22 +00:00
169 lines
5.3 KiB
Objective-C
169 lines
5.3 KiB
Objective-C
// 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-2005 Steve Nygard
|
|
|
|
#import "CDObjCSegmentProcessor.h"
|
|
|
|
#include <mach-o/arch.h>
|
|
|
|
#import <Foundation/Foundation.h>
|
|
#import "CDClassDump.h"
|
|
#import "CDDylibCommand.h"
|
|
#import "CDMachOFile.h"
|
|
#import "CDOCCategory.h"
|
|
#import "CDOCClass.h"
|
|
#import "CDOCIvar.h"
|
|
#import "CDOCMethod.h"
|
|
#import "CDOCModule.h"
|
|
#import "CDOCProtocol.h"
|
|
#import "CDOCSymtab.h"
|
|
#import "CDSection.h"
|
|
#import "CDSegmentCommand.h"
|
|
#import "NSArray-Extensions.h"
|
|
#import "CDObjCSegmentProcessor-Private.h"
|
|
|
|
@implementation CDObjCSegmentProcessor
|
|
|
|
- (id)initWithMachOFile:(CDMachOFile *)aMachOFile;
|
|
{
|
|
if ([super init] == nil)
|
|
return nil;
|
|
|
|
machOFile = [aMachOFile retain];
|
|
modules = [[NSMutableArray alloc] init];
|
|
protocolsByName = [[NSMutableDictionary alloc] init];
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc;
|
|
{
|
|
[machOFile release];
|
|
[modules release];
|
|
[protocolsByName release];
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)process;
|
|
{
|
|
[self processProtocolSection];
|
|
[self processModules];
|
|
}
|
|
|
|
- (void)appendFormattedString:(NSMutableString *)resultString classDump:(CDClassDump *)aClassDump;
|
|
{
|
|
int count, index;
|
|
NSMutableArray *allClasses;
|
|
NSArray *protocolNames;
|
|
|
|
allClasses = [[NSMutableArray alloc] init];
|
|
|
|
count = [modules count];
|
|
for (index = 0; index < count; index++) {
|
|
NSArray *moduleClasses, *moduleCategories;
|
|
|
|
moduleClasses = [[[modules objectAtIndex:index] symtab] classes];
|
|
if (moduleClasses != nil)
|
|
[allClasses addObjectsFromArray:moduleClasses];
|
|
|
|
moduleCategories = [[[modules objectAtIndex:index] symtab] categories];
|
|
if (moduleCategories != nil)
|
|
[allClasses addObjectsFromArray:moduleCategories];
|
|
}
|
|
|
|
// TODO: Sort protocols by dependency
|
|
// TODO (2004-01-30): It looks like protocols might be defined in more than one file. i.e. NSObject.
|
|
// TODO (2004-02-02): Looks like we need to record the order the protocols were encountered, or just always sort protocols
|
|
protocolNames = [[protocolsByName allKeys] sortedArrayUsingSelector:@selector(compare:)];
|
|
|
|
if ([protocolNames count] > 0 || [allClasses count] > 0) {
|
|
const NXArchInfo *archInfo;
|
|
|
|
[resultString appendString:@"/*\n"];
|
|
[resultString appendFormat:@" * File: %@\n", [machOFile filename]];
|
|
|
|
archInfo = NXGetArchInfoFromCpuType([machOFile cpuType], [machOFile cpuSubtype]);
|
|
if (archInfo != NULL)
|
|
[resultString appendFormat:@" * Arch: %s (%s)\n", archInfo->description, archInfo->name];
|
|
|
|
if ([machOFile filetype] == MH_DYLIB) {
|
|
CDDylibCommand *identifier;
|
|
|
|
identifier = [machOFile dylibIdentifier];
|
|
if (identifier != nil)
|
|
[resultString appendFormat:@" * Current version: %@, Compatibility version: %@\n",
|
|
[identifier formattedCurrentVersion], [identifier formattedCompatibilityVersion]];
|
|
}
|
|
[resultString appendString:@" */\n\n"];
|
|
}
|
|
|
|
count = [protocolNames count];
|
|
for (index = 0; index < count; index++) {
|
|
CDOCProtocol *aProtocol;
|
|
|
|
aProtocol = [protocolsByName objectForKey:[protocolNames objectAtIndex:index]];
|
|
[aProtocol appendToString:resultString classDump:aClassDump symbolReferences:nil];
|
|
}
|
|
|
|
if ([aClassDump shouldSortClassesByInheritance] == YES) {
|
|
[allClasses sortTopologically];
|
|
} else if ([aClassDump shouldSortClasses] == YES)
|
|
[allClasses sortUsingSelector:@selector(ascendingCompareByName:)];
|
|
|
|
count = [allClasses count];
|
|
for (index = 0; index < count; index++)
|
|
[[allClasses objectAtIndex:index] appendToString:resultString classDump:aClassDump symbolReferences:nil];
|
|
|
|
[allClasses release];
|
|
}
|
|
|
|
- (void)registerStructuresWithObject:(id <CDStructureRegistration>)anObject phase:(int)phase;
|
|
{
|
|
int count, index;
|
|
NSArray *protocolNames;
|
|
|
|
count = [modules count];
|
|
for (index = 0; index < count; index++)
|
|
[[[modules objectAtIndex:index] symtab] registerStructuresWithObject:anObject phase:phase];
|
|
|
|
protocolNames = [[protocolsByName allKeys] sortedArrayUsingSelector:@selector(compare:)];
|
|
count = [protocolNames count];
|
|
for (index = 0; index < count; index++) {
|
|
CDOCProtocol *aProtocol;
|
|
|
|
aProtocol = [protocolsByName objectForKey:[protocolNames objectAtIndex:index]];
|
|
[aProtocol registerStructuresWithObject:anObject phase:phase];
|
|
}
|
|
}
|
|
|
|
- (NSString *)description;
|
|
{
|
|
return [NSString stringWithFormat:@"[%@] machOFile: %@", NSStringFromClass([self class]), [machOFile filename]];
|
|
}
|
|
|
|
- (void)registerClassesWithObject:(NSMutableDictionary *)aDictionary;
|
|
{
|
|
NSString *importBaseName;
|
|
|
|
importBaseName = [machOFile importBaseName];
|
|
if (importBaseName != nil) {
|
|
int count, index;
|
|
|
|
count = [modules count];
|
|
for (index = 0; index < count; index++) {
|
|
[[modules objectAtIndex:index] registerClassesWithObject:aDictionary frameworkName:importBaseName];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)generateSeparateHeadersClassDump:(CDClassDump *)aClassDump;
|
|
{
|
|
int count, index;
|
|
|
|
count = [modules count];
|
|
for (index = 0; index < count; index++)
|
|
[[modules objectAtIndex:index] generateSeparateHeadersClassDump:aClassDump];
|
|
}
|
|
|
|
@end
|