| // 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-2007 Steve Nygard |
| |
| #import "CDFatFile.h" |
| |
| #include <mach-o/arch.h> |
| #include <mach-o/swap.h> |
| #import <Foundation/Foundation.h> |
| #import "CDFatArch.h" |
| #import "CDMachOFile.h" |
| |
| // The fat_header and fat_arch structures are stored in big endian-byte order. |
| // TODO (2005-07-27): For Intel, we'll need to swap those structs. |
| |
| @implementation CDFatFile |
| |
| - (id)initWithFilename:(NSString *)aFilename; |
| { |
| BOOL shouldSwapBytes; |
| |
| if ([super init] == nil) |
| return nil; |
| |
| shouldSwapBytes = NO; |
| filename = [aFilename retain]; |
| |
| data = [[NSData alloc] initWithContentsOfMappedFile:filename]; |
| if (data == nil) { |
| NSLog(@"Couldn't read file: %@", filename); |
| [self release]; |
| return nil; |
| } |
| |
| header = *(struct fat_header *)[data bytes]; |
| if (header.magic == FAT_CIGAM) { |
| shouldSwapBytes = YES; |
| swap_fat_header(&header, CD_THIS_BYTE_ORDER); |
| } |
| |
| if (header.magic != FAT_MAGIC) { |
| [self release]; |
| return nil; |
| } |
| |
| arches = [[NSMutableArray alloc] init]; |
| [self _processFatArchesWithPointer:[data bytes] + sizeof(struct fat_header) swapBytes:shouldSwapBytes]; |
| |
| return self; |
| } |
| |
| - (void)dealloc; |
| { |
| [filename release]; |
| [data release]; |
| [arches release]; |
| |
| [super dealloc]; |
| } |
| |
| - (void)_processFatArchesWithPointer:(const void *)ptr swapBytes:(BOOL)shouldSwapBytes; |
| { |
| unsigned int count, index; |
| |
| count = [self fatCount]; |
| for (index = 0; index < count; index++) { |
| CDFatArch *fatArch; |
| |
| fatArch = [[CDFatArch alloc] initWithPointer:ptr swapBytes:shouldSwapBytes]; |
| [arches addObject:fatArch]; |
| [fatArch release]; |
| ptr += sizeof(struct fat_arch); |
| } |
| } |
| |
| - (NSString *)filename; |
| { |
| return filename; |
| } |
| |
| - (unsigned int)fatCount; |
| { |
| return header.nfat_arch; |
| } |
| |
| - (CDFatArch *)fatArchWithName:(NSString *)archName; |
| { |
| if (archName == nil) { |
| CDFatArch *fatArch; |
| |
| fatArch = [self localArchitecture]; |
| if (fatArch == nil && [arches count] > 0) |
| fatArch = [arches objectAtIndex:0]; |
| |
| return fatArch; |
| } |
| |
| return [self _fatArchWithName:archName]; |
| } |
| |
| - (CDFatArch *)_fatArchWithName:(NSString *)archName; |
| { |
| unsigned int count, index; |
| |
| count = [arches count]; |
| for (index = 0; index < count; index++) { |
| CDFatArch *fatArch; |
| |
| fatArch = [arches objectAtIndex:index]; |
| if ([[fatArch archName] isEqual:archName]) |
| return fatArch; |
| } |
| |
| return nil; |
| } |
| |
| - (CDFatArch *)localArchitecture; |
| { |
| const NXArchInfo *archInfo; |
| |
| archInfo = NXGetLocalArchInfo(); |
| if (archInfo == NULL) { |
| NSLog(@"Couldn't get local architecture"); |
| return nil; |
| } |
| |
| //NSLog(@"Local arch: %d, %s (%s)", archInfo->cputype, archInfo->description, archInfo->name); |
| |
| // TODO (2007-11-04): Hmm. Search first for exact match, then fall back to main cputype. |
| return [self _fatArchWithName:CDNameForCPUType(archInfo->cputype, archInfo->cpusubtype)]; |
| } |
| |
| - (NSString *)description; |
| { |
| return [NSString stringWithFormat:@"[%p]CDFatFile with %u arches", self, [self fatCount]]; |
| #if 0 |
| return [NSString stringWithFormat:@"magic: 0x%08x, cputype: %d, cpusubtype: %d, filetype: %d, ncmds: %d, sizeofcmds: %d, flags: 0x%x", |
| header.magic, header.cputype, header.cpusubtype, header.filetype, header.ncmds, header.sizeofcmds, header.flags]; |
| #endif |
| } |
| |
| - (NSArray *)archNames; |
| { |
| NSMutableArray *archNames; |
| unsigned int count, index; |
| |
| archNames = [NSMutableArray array]; |
| count = [arches count]; |
| for (index = 0; index < count; index++) |
| [archNames addObject:[[arches objectAtIndex:index] archName]]; |
| |
| return archNames; |
| } |
| |
| @end |