blob: 44a952c3617e030e34084ffa9ce26cb61fa53369 [file] [log] [blame]
// -*- mode: ObjC -*-
// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
// Copyright (C) 1997-2019 Steve Nygard.
#import "CDFile.h"
#include <mach-o/arch.h>
#import "CDFatFile.h"
#import "CDMachOFile.h"
#import "CDSearchPathState.h"
NSString *CDImportNameForPath(NSString *path)
{
NSString *name = [path lastPathComponent];
// Remove all extensions (make sure extensions like .a.dylib are covered)
NSString *nameWithExtensions = name;
for (NSInteger i = ([nameWithExtensions length] - 1); i >= 0; i--) {
if ([nameWithExtensions characterAtIndex:i] == '.')
name = [name substringToIndex:i];
}
NSString *libPrefix = @"lib";
if ([name hasPrefix:libPrefix])
name = [name substringFromIndex:[libPrefix length]];
return name;
}
NSString *CDNameForCPUType(cpu_type_t cputype, cpu_subtype_t cpusubtype)
{
const NXArchInfo *archInfo = NXGetArchInfoFromCpuType(cputype, cpusubtype);
if (archInfo != NULL)
return [NSString stringWithUTF8String:archInfo->name];
// Special cases until the built-in function recognizes these.
switch (cputype) {
case CPU_TYPE_ARM: {
switch (cpusubtype) {
case 11: return @"armv7s"; // Not recognized in 10.8.4
}
break;
}
case CPU_TYPE_ARM | CPU_ARCH_ABI64: {
switch (cpusubtype) {
case CPU_SUBTYPE_ARM_ALL: return @"arm64"; // Not recognized in 10.8.4
}
break;
}
default: break;
}
return [NSString stringWithFormat:@"0x%x:0x%x", cputype, cpusubtype];
}
CDArch CDArchFromName(NSString *name)
{
CDArch arch;
arch.cputype = CPU_TYPE_ANY;
arch.cpusubtype = 0;
if (name == nil)
return arch;
const NXArchInfo *archInfo = NXGetArchInfoFromName([name UTF8String]);
if (archInfo == NULL) {
if ([name isEqualToString:@"armv7s"]) { // Not recognized in 10.8.4
arch.cputype = CPU_TYPE_ARM;
arch.cpusubtype = 11;
} else if ([name isEqualToString:@"arm64"]) { // Not recognized in 10.8.4
arch.cputype = CPU_TYPE_ARM | CPU_ARCH_ABI64;
arch.cpusubtype = CPU_SUBTYPE_ARM_ALL;
} else {
NSString *ignore;
NSScanner *scanner = [[NSScanner alloc] initWithString:name];
if ([scanner scanHexInt:(uint32_t *)&arch.cputype]
&& [scanner scanString:@":" intoString:&ignore]
&& [scanner scanHexInt:(uint32_t *)&arch.cpusubtype]) {
// Great!
//NSLog(@"scanned 0x%08x : 0x%08x from '%@'", arch.cputype, arch.cpusubtype, name);
} else {
arch.cputype = CPU_TYPE_ANY;
arch.cpusubtype = 0;
}
}
} else {
arch.cputype = archInfo->cputype;
arch.cpusubtype = archInfo->cpusubtype;
}
return arch;
}
BOOL CDArchUses64BitABI(CDArch arch)
{
return (arch.cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64;
}
BOOL CDArchUses64BitLibraries(CDArch arch)
{
return (arch.cpusubtype & CPU_SUBTYPE_LIB64) == CPU_SUBTYPE_LIB64;
}
#pragma mark -
@interface CDFile ()
@end
#pragma mark -
@implementation CDFile
{
NSString *_filename;
NSData *_data;
CDSearchPathState *_searchPathState;
}
// Returns CDFatFile or CDMachOFile
+ (id)fileWithContentsOfFile:(NSString *)filename searchPathState:(CDSearchPathState *)searchPathState;
{
NSData *data = [NSData dataWithContentsOfMappedFile:filename];
CDFatFile *fatFile = [[CDFatFile alloc] initWithData:data filename:filename searchPathState:searchPathState];
if (fatFile != nil)
return fatFile;
CDMachOFile *machOFile = [[CDMachOFile alloc] initWithData:data filename:filename searchPathState:searchPathState];
return machOFile;
}
- (id)initWithData:(NSData *)data filename:(NSString *)filename searchPathState:(CDSearchPathState *)searchPathState;
{
if ((self = [super init])) {
// Otherwise reading the magic number fails.
if ([data length] < 4) {
return nil;
}
_filename = filename;
_data = data;
_searchPathState = searchPathState;
}
return self;
}
#pragma mark -
// Return YES on success. If oArchPtr is not NULL, return the best match.
// Return NO on failure, oArchPtr is untouched.
- (BOOL)bestMatchForLocalArch:(CDArch *)oArchPtr;
{
const NXArchInfo *archInfo = NXGetLocalArchInfo();
if (archInfo == NULL)
return NO;
CDArch arch = { archInfo->cputype, archInfo->cpusubtype };
if ([self bestMatchForArch:&arch]) {
if (oArchPtr != NULL)
*oArchPtr = arch;
return YES;
}
return NO;
}
- (BOOL)bestMatchForArch:(CDArch *)ioArchPtr;
{
return NO;
}
- (CDMachOFile *)machOFileWithArch:(CDArch)arch;
{
return nil;
}
- (NSString *)architectureNameDescription;
{
return nil;
}
@end