Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift support* for the class-dump #78

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
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
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ The latest version and information is available at:
The source code is also available from my Github repository at:

https://github.com/nygard/class-dump

"Swift support"
==========

I added "Swift support" for class-dump.

Now, this tool can dump Objective-C headers even the MachO file uses Swift and ObjC at the same time.
Notice, only ObjC headers can be dumped!

LAST, THIS IS AN EXPERIMENTAL VERSION.

我为class-dump添加了"Swift支持"。

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should use English all the time.


现在,这个工具可以dump出可执行文件的Objective-C头文件,即使那个MachO文件同时使用了Swift和ObjC。请注意只有ObjC类的头文件可以被dump出来!

最后,这只是一个试验版本。

Usage
-----
Expand Down
76 changes: 64 additions & 12 deletions Source/CDDataCursor.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,27 @@ - (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 @@ -56,7 +68,10 @@ - (NSUInteger)remaining;
- (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 @@ -71,7 +86,10 @@ - (uint8_t)readByte;
- (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 @@ -86,7 +104,10 @@ - (uint16_t)readLittleInt16;
- (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 @@ -101,7 +122,10 @@ - (uint32_t)readLittleInt32;
- (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 @@ -118,7 +142,10 @@ - (uint64_t)readLittleInt64;
- (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 @@ -133,7 +160,10 @@ - (uint16_t)readBigInt16;
- (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 @@ -148,7 +178,10 @@ - (uint32_t)readBigInt32;
- (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 +225,10 @@ - (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 +239,10 @@ - (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 +258,10 @@ - (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 All @@ -234,7 +279,10 @@ - (NSString *)readStringOfLength:(NSUInteger)length encoding:(NSStringEncoding)e
NSLog(@"Error: malloc() failed.");
return nil;
}

if (_offset == -'S') {
NSLog(@"Warning: Maybe meet a Swift object at 1 of %s",__cmd);
return @"Swift";
}
strncpy(buf, (const char *)[_data bytes] + _offset, length);
buf[length] = 0;

Expand All @@ -248,6 +296,10 @@ - (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
5 changes: 5 additions & 0 deletions Source/CDLCDyldInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
_dyldInfoCommand.export_off = [cursor readInt32];
_dyldInfoCommand.export_size = [cursor readInt32];

if (_dyldInfoCommand.cmd == -'S' || _dyldInfoCommand.cmdsize == -'S' || _dyldInfoCommand.rebase_off == -'S' || _dyldInfoCommand.rebase_size == -'S' || _dyldInfoCommand.bind_off == -'S' || _dyldInfoCommand.bind_size == -'S' || _dyldInfoCommand.weak_bind_off == -'S' || _dyldInfoCommand.weak_bind_size == -'S' || _dyldInfoCommand.lazy_bind_off == -'S' || _dyldInfoCommand.lazy_bind_size == -'S' || _dyldInfoCommand.export_off == -'S' || _dyldInfoCommand.export_size == -'S') {
NSLog(@"Warning: Meet Swift object at %s",__cmd);
return nil;
}

#if 0
NSLog(@" cmdsize: %08x", _dyldInfoCommand.cmdsize);
NSLog(@" rebase_off: %08x", _dyldInfoCommand.rebase_off);
Expand Down
17 changes: 11 additions & 6 deletions Source/CDMachOFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ - (NSString *)stringAtAddress:(NSUInteger)address;

CDLCSegment *segment = [self segmentContainingAddress:address];
if (segment == nil) {
NSLog(@"Error: Cannot find offset for address 0x%08lx in stringAtAddress:", address);
exit(5);
return nil;
NSLog(@"Warning: Cannot find offset for address 0x%08lx in stringAtAddress:", address);
// exit(5);
return @"Swift";
}

if ([segment isProtected]) {
Expand All @@ -349,7 +349,10 @@ - (NSString *)stringAtAddress:(NSUInteger)address;
NSUInteger offset = [self dataOffsetForAddress:address];
if (offset == 0)
return nil;

if (offset == -'S') {
NSLog(@"Warning: Meet Swift object at %s",__cmd);
return @"Swift";
}
ptr = (uint8_t *)[self.data bytes] + offset;

return [[NSString alloc] initWithBytes:ptr length:strlen(ptr) encoding:NSASCIIStringEncoding];
Expand All @@ -362,8 +365,10 @@ - (NSUInteger)dataOffsetForAddress:(NSUInteger)address;

CDLCSegment *segment = [self segmentContainingAddress:address];
if (segment == nil) {
NSLog(@"Error: Cannot find offset for address 0x%08lx in dataOffsetForAddress:", address);
exit(5);
NSLog(@"Warning: Cannot find offset for address 0x%08lx in dataOffsetForAddress:", address);
NSLog(@"Warning: Maybe meet a Swift object at %s",__cmd);
// exit(5);
return -'S';
}

// if ([segment isProtected]) {
Expand Down
33 changes: 20 additions & 13 deletions Source/CDObjectiveC2Processor.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,17 @@ - (CDOCProtocol *)protocolAtAddress:(uint64_t)address;
{
if (address == 0)
return nil;

CDOCProtocol *protocol = [self.protocolUniquer protocolWithAddress:address];
if (protocol == nil) {
protocol = [[CDOCProtocol alloc] init];
[self.protocolUniquer setProtocol:protocol withAddress:address];

CDMachOFileDataCursor *cursor = [[CDMachOFileDataCursor alloc] initWithFile:self.machOFile address:address];
if ([cursor offset] == -'S') {
NSLog(@"Warning: Meet Swift object at %s",__cmd);
return nil;
}
NSParameterAssert([cursor offset] != 0);

struct cd_objc2_protocol objc2Protocol;
objc2Protocol.isa = [cursor readPtr];
objc2Protocol.name = [cursor readPtr];
Expand Down Expand Up @@ -320,18 +322,23 @@ - (NSArray *)loadPropertiesAtAddress:(uint64_t)address;

listHeader.entsize = [cursor readInt32];
listHeader.count = [cursor readInt32];
NSParameterAssert(listHeader.entsize == 2 * [self.machOFile ptrSize]);

for (uint32_t index = 0; index < listHeader.count; index++) {
struct cd_objc2_property objc2Property;

objc2Property.name = [cursor readPtr];
objc2Property.attributes = [cursor readPtr];
NSString *name = [self.machOFile stringAtAddress:objc2Property.name];
NSString *attributes = [self.machOFile stringAtAddress:objc2Property.attributes];

CDOCProperty *property = [[CDOCProperty alloc] initWithName:name attributes:attributes];
[properties addObject:property];
if (listHeader.entsize == 2 * [self.machOFile ptrSize]) {
for (uint32_t index = 0; index < listHeader.count; index++) {
struct cd_objc2_property objc2Property;

objc2Property.name = [cursor readPtr];
objc2Property.attributes = [cursor readPtr];
NSString *name = [self.machOFile stringAtAddress:objc2Property.name];
NSString *attributes = [self.machOFile stringAtAddress:objc2Property.attributes];

CDOCProperty *property = [[CDOCProperty alloc] initWithName:name attributes:attributes];
[properties addObject:property];
}
}
else
{
return nil;
}
}

Expand Down