blob: 4521bc927b9ec6d14f2f734fd9e9c5c98595e021 [file] [log] [blame]
// 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-2006 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];
}
- (BOOL)hasModules;
{
return [modules count] > 0;
}
- (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