Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
build

34 changes: 34 additions & 0 deletions CDFatArch64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// -*- 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" // For CDArch

@class CDDataCursor;
@class CDFatFile, CDMachOFile;

@interface CDFatArch64 : NSObject

- (id)initWithMachOFile:(CDMachOFile *)machOFile bigendian:(bool)isBigEndian;
- (id)initWithDataCursor:(CDDataCursor *)cursor bigendian:(bool)isBigEndian;

@property (assign) cpu_type_t cputype;
@property (assign) cpu_subtype_t cpusubtype;
@property (assign) uint64_t offset;
@property (assign) uint64_t size;
@property (assign) uint32_t align;

@property (nonatomic, readonly) cpu_type_t maskedCPUType;
@property (nonatomic, readonly) cpu_subtype_t maskedCPUSubtype;
@property (nonatomic, readonly) BOOL uses64BitABI;
@property (nonatomic, readonly) BOOL uses64BitLibraries;

@property (weak) CDFatFile *fatFile;

@property (nonatomic, readonly) CDArch arch;
@property (nonatomic, readonly) NSString *archName;

@property (nonatomic, readonly) CDMachOFile *machOFile;

@end
137 changes: 137 additions & 0 deletions CDFatArch64.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// -*- 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 "CDFatArch64.h"

#include <mach-o/fat.h>
#import "CDDataCursor.h"
#import "CDFatFile.h"
#import "CDMachOFile.h"

@implementation CDFatArch64
{
__weak CDFatFile *_fatFile;
bool _isSwapped;

// This is essentially struct fat_arch, but this way our property accessors can be synthesized.
cpu_type_t _cputype;
cpu_subtype_t _cpusubtype;
uint64_t _offset;
uint64_t _size;
uint32_t _align;
uint32_t _reserved;

CDMachOFile *_machOFile; // Lazily create this.
}

- (id)initWithMachOFile:(CDMachOFile *)machOFile bigendian:(bool)isBigEndian
{
if ((self = [super init])) {
_machOFile = machOFile;

if (isBigEndian == true) {
_cputype = _machOFile.cputype;
_cpusubtype = _machOFile.cpusubtype;
_offset = 0; // Would be filled in when this is written to disk
_size = (uint64_t)[_machOFile.data length];
_align = 12; // 2**12 = 4096 (0x1000)
_reserved = 0;
_isSwapped = false;
} else {
_cputype = OSSwapInt32(_machOFile.cputype);
_cpusubtype = OSSwapInt32(_machOFile.cpusubtype);
_offset = 0; // Would be filled in when this is written to disk
_size = OSSwapInt64((uint64_t)[_machOFile.data length]);
_align = 0x0C000000; // 2**12 = 4096 (0x1000)
_reserved = 0;
_isSwapped = true;
}
}

return self;
}

- (id)initWithDataCursor:(CDDataCursor *)cursor bigendian:(bool)isBigEndian
{
if ((self = [super init])) {
if (isBigEndian == true) {
_cputype = [cursor readBigInt32];
_cpusubtype = [cursor readBigInt32];
_offset = [cursor readBigInt64];
_size = [cursor readBigInt64];
_align = [cursor readBigInt32];
_reserved = [cursor readBigInt32];
_isSwapped = false;
} else {
_cputype = [cursor readLittleInt32];
_cpusubtype = [cursor readLittleInt32];
_offset = [cursor readLittleInt64];
_size = [cursor readLittleInt64];
_align = [cursor readLittleInt32];
_reserved = [cursor readLittleInt32];
_isSwapped = true;
}

//NSLog(@"self: %@", self);
}

return self;
}

#pragma mark - Debugging

- (NSString *)description;
{
return [NSString stringWithFormat:@"64 bit ABI? %d, cputype: 0x%08x, cpusubtype: 0x%08x, offset: 0x%16llx (%16llu), size: 0x%16llx (%16llu), align: 2^%u (%x), arch name: %@",
self.uses64BitABI, self.cputype, self.cpusubtype, self.offset, self.offset, self.size, self.size,
self.align, 1 << self.align, self.archName];
}

#pragma mark -

- (cpu_type_t)maskedCPUType;
{
return self.cputype & ~CPU_ARCH_MASK;
}

- (cpu_subtype_t)maskedCPUSubtype;
{
return self.cpusubtype & ~CPU_SUBTYPE_MASK;
}

- (BOOL)uses64BitABI;
{
return CDArchUses64BitABI(self.arch);
}

- (BOOL)uses64BitLibraries;
{
return CDArchUses64BitLibraries(self.arch);
}

- (CDArch)arch;
{
CDArch arch = { self.cputype, self.cpusubtype };

return arch;
}

// Must not return nil.
- (NSString *)archName;
{
return CDNameForCPUType(self.cputype, self.cpusubtype);
}

- (CDMachOFile *)machOFile;
{
if (_machOFile == nil) {
NSData *data = [NSData dataWithBytesNoCopy:((uint8_t *)[self.fatFile.data bytes] + self.offset) length:self.size freeWhenDone:NO];
_machOFile = [[CDMachOFile alloc] initWithData:data filename:self.fatFile.filename searchPathState:self.fatFile.searchPathState isCache:NO];
}

return _machOFile;
}

@end
Binary file added Source/.DS_Store
Binary file not shown.
14 changes: 13 additions & 1 deletion Source/CDClassDump.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
#import "CDTypeController.h"
#import "CDSearchPathState.h"

#include <mach-o/dyld.h>

NSString *CDErrorDomain_ClassDump = @"CDErrorDomain_ClassDump";

NSString *CDErrorKey_Exception = @"CDErrorKey_Exception";

extern NSString *cacheName;

@interface CDClassDump ()
@end

Expand Down Expand Up @@ -201,6 +205,8 @@ - (void)recursivelyVisit:(CDVisitor *)visitor;
[visitor didEndVisiting];
}

extern intptr_t _dyld_get_image_slide(const struct mach_header* mh);

- (CDMachOFile *)machOFileWithName:(NSString *)name;
{
NSString *adjustedName = nil;
Expand Down Expand Up @@ -232,7 +238,13 @@ - (CDMachOFile *)machOFileWithName:(NSString *)name;

CDMachOFile *machOFile = _machOFilesByName[adjustedName];
if (machOFile == nil) {
CDFile *file = [CDFile fileWithContentsOfFile:adjustedName searchPathState:self.searchPathState];
CDFile *file = nil;

if (cacheName != nil)
file = [CDFile fileWithContentsOfFile:adjustedName cache:cacheName searchPathState:self.searchPathState isCache:YES];

if (file == nil)
file = [CDFile fileWithContentsOfFile:adjustedName cache:nil searchPathState:self.searchPathState isCache:NO];

if (file == nil || [self loadFile:file error:NULL] == NO)
NSLog(@"Warning: Failed to load: %@", adjustedName);
Expand Down
76 changes: 72 additions & 4 deletions Source/CDDataCursor.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,28 @@ - (const void *)bytes;

- (void)setOffset:(NSUInteger)newOffset;
{
if (newOffset <= [_data length]) {
_offset = newOffset;
} else {
[NSException raise:NSRangeException format:@"Trying to seek past end of data."];
if (newOffset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
_offset = -'S';
}
else
{
if (newOffset <= [_data length]) {
_offset = newOffset;
} else {
[NSException raise:NSRangeException format:@"Trying to seek past end of data."];
}
}
}

- (void)advanceByLength:(NSUInteger)length;
{
if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
_offset += 10;
return;
}

if (_offset + length <= [_data length]) {
_offset += length;
} else {
Expand All @@ -57,6 +70,11 @@ - (uint8_t)readByte;
{
uint8_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
result = OSReadLittleInt16([_data bytes], _offset) & 0xFF;
_offset += sizeof(result);
Expand All @@ -72,6 +90,11 @@ - (uint16_t)readLittleInt16;
{
uint16_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
result = OSReadLittleInt16([_data bytes], _offset);
_offset += sizeof(result);
Expand All @@ -87,6 +110,11 @@ - (uint32_t)readLittleInt32;
{
uint32_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
result = OSReadLittleInt32([_data bytes], _offset);
_offset += sizeof(result);
Expand All @@ -102,6 +130,11 @@ - (uint64_t)readLittleInt64;
{
uint64_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
// uint8_t *ptr = [_data bytes] + _offset;
// NSLog(@"%016llx: %02x %02x %02x %02x %02x %02x %02x %02x", _offset, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
Expand All @@ -119,6 +152,11 @@ - (uint16_t)readBigInt16;
{
uint16_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
result = OSReadBigInt16([_data bytes], _offset);
_offset += sizeof(result);
Expand All @@ -134,6 +172,11 @@ - (uint32_t)readBigInt32;
{
uint32_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
result = OSReadBigInt32([_data bytes], _offset);
_offset += sizeof(result);
Expand All @@ -149,6 +192,11 @@ - (uint64_t)readBigInt64;
{
uint64_t result;

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return 0;
}

if (_offset + sizeof(result) <= [_data length]) {
result = OSReadBigInt64([_data bytes], _offset);
_offset += sizeof(result);
Expand Down Expand Up @@ -192,6 +240,11 @@ - (double)readLittleFloat64;

- (void)appendBytesOfLength:(NSUInteger)length intoData:(NSMutableData *)data;
{
if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return;
}

if (_offset + length <= [_data length]) {
[data appendBytes:(uint8_t *)[_data bytes] + _offset length:length];
_offset += length;
Expand All @@ -202,6 +255,11 @@ - (void)appendBytesOfLength:(NSUInteger)length intoData:(NSMutableData *)data;

- (void)readBytesOfLength:(NSUInteger)length intoBuffer:(void *)buf;
{
if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return;
}

if (_offset + length <= [_data length]) {
memcpy(buf, (uint8_t *)[_data bytes] + _offset, length);
_offset += length;
Expand All @@ -217,6 +275,11 @@ - (BOOL)isAtEnd;

- (NSString *)readCString;
{
if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
return @"Swift";
}

return [self readStringOfLength:strlen((const char *)[_data bytes] + _offset) encoding:NSASCIIStringEncoding];
}

Expand Down Expand Up @@ -248,6 +311,11 @@ - (NSString *)readStringOfLength:(NSUInteger)length encoding:(NSStringEncoding)e
return str;
}
} else {
if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at 2 of %s",__cmd);
return @"Swift";
}

[NSException raise:NSRangeException format:@"Trying to read past end in %s", __cmd];
}

Expand Down
4 changes: 2 additions & 2 deletions Source/CDFatArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

@interface CDFatArch : NSObject

- (id)initWithMachOFile:(CDMachOFile *)machOFile;
- (id)initWithDataCursor:(CDDataCursor *)cursor;
- (id)initWithMachOFile:(CDMachOFile *)machOFile bigendian:(bool)isBigEndian;
- (id)initWithDataCursor:(CDDataCursor *)cursor bigendian:(bool)isBigEndian;

@property (assign) cpu_type_t cputype;
@property (assign) cpu_subtype_t cpusubtype;
Expand Down
Loading