Download: * 0.2a: http://networkpx.googlecode.com/files/class-dump-z_0.2a.tar.gz (Windows not yet supported). * 0.2-0: http://networkpx.googlecode.com/files/class-dump-z_0.2-0.tar.gz .
``` Usage: class-dump-z []
where options are:
Analysis: -p Convert undeclared getters and setters into properties (propertize). -h proto Hide methods which already appears in an adopted protocol. -h super Hide inherited methods. -y Choose the sysroot. Default to the path of latest iPhoneOS SDK, or /. -u Choose a specific architecture in a fat binary (e.g. armv6, armv7, etc.)
Formatting: -a Print ivar offsets -A Print implementation VM addresses. -k Show additional comments. -k -k Show even more comments. -R Show pointer declarations as int a instead of int a. -N Keep the raw struct names (e.g. do no replace __CFArray* with CFArrayRef). -b Put a space after the +/- sign (i.e. + (void)... instead of +(void)...). -i Read and update signature hints file.
Filtering: -C Only display types with (original) name matching the RegExp (in PCRE syntax). -f Only display methods with (original) name matching the RegExp. -g Display exported classes only. -X Ignore all types (except categories) with a prefix in the comma-separated list. -h cats Hide categories. -h dogs Hide protocols.
Sorting: -S Sort types in alphabetical order. -s Sort methods in alphabetical order. -z Sort methods alphabetically but put class methods and -init... first.
Output: -H Separate into header files -o Put header files into this directory instead of current directory. ```
Why a yet another class-dump?
class-dump is a command-line tool to extract Objective-C class interfaces, written by Steve Nygard 17 years ago. The development however paused in 2007 at version 3.1.2, without support for the newest ABI.
This caused the birth of class-dump-x by Holly Lee in 2008. But being a straight modified version of class-dump, it inherited some of the problems, e.g. the ivar offsets are calculated wrongly, properties are not supported, etc.
I, using class-dump-x a lot for reverse engineering, finds that the ivar offset problem is hard to get over with. Having no answers a few months after a bug report, I decided to just fix the problem myself — hence class-dump-z is started.
(While I was creating class-dump-z, the original class-dump development suddenly reactivated at July 1st. The newest version 3.2 does support 2.0 ABI now, but the ivar offset info is even worse than class-dump-x.)
Why you don't want to use class-dump-z
Instead of a generic-purpose class dumper, class-dump-z was written with iPhoneOS development in mind. Therefore, the following features will probably never be implemented: * 64-bit support. (Unless there is a 4 GiB RAM iPhone.) * Objective-C 1.0 ABI. In general, if you want to dump Mac OS X, you should use the original class-dump. But if you're dumping iPhoneOS binaries, class-dump-z is definitely the better choice.
Features
10x the speed
| Time to dump... | class-dump-x 3.1.2 | class-dump 3.3.1 | class-dump-z 0.2-0 | |:--------------------|:-------------------|:-----------------|:-------------------| | UIKit 2.0 (run in Mac OS X) | 2.2s | 1.8s | 0.13s | | UIKit 3.1 (run in Mac OS X) | 2.9s | 2.1s | 0.19s | | CoreData 3.0 (run in iPhoneOS) | 21s | - | 2.6s |
time class-dump-? -a -A UIKit > /dev/null
class-dump-z is written from scratch using C++ avoiding using dynamic calls, unlike class-dump and class-dump-x which are written in Objective-C. Removing these unnecessary calls makes class-dump-z near 10 times faster than the precedences.
Portable
| Platforms | class-dump-x 3.1.2 | class-dump 3.3.1 | class-dump-z 0.2-0 | |:--------------|:-------------------|:-----------------|:-------------------| | Mac OS X 10.6 | ✓ | ✓ | ✓ | | iPhoneOS 3.1 | ✓ | ✗ | ✓ | | Linux | ✗ | ✗ | ✓ | | Windows | ✗ | ✗ | ✓ |
Since class-dump-z is written in C++, it is very easy to port to other platforms. Currently Mac OS X 10.6, iPhoneOS 3.1, Linux (x86 and amd64) and Windows (≥XP) are officially supported.
Correct ivar offsets
UIRemoveControlMultiSelectButton
3.1UIMoreListController
3.1
class-dump-x 3.1.2
unsigned int _isHighlighted:1; // 68 = 0x44
unsigned int _isSelected:1; // 69 = 0x45
UITableView *_table; // 92 = 0x5c
BOOL _allowsCustomizing; // 96 = 0x60
NSArray *_moreViewControllers; // 97 = 0x61
UIMoreListCellLayoutManager *_layoutManager; // 101 = 0x65
class-dump 3.3.1
unsigned int _isHighlighted:1;
unsigned int _isSelected:1;
(No offsets shown. Don't know why.)UITableView *_table;
BOOL _allowsCustomizing;
NSArray *_moreViewControllers;
UIMoreListCellLayoutManager *_layoutManager;
class-dump-z 0.2-0
unsigned _isHighlighted : 1; // 68 = 0x44
unsigned _isSelected : 1; // 68 = 0x44
UITableView* _table; // 92 = 0x5c
BOOL _allowsCustomizing; // 96 = 0x60
NSArray* _moreViewControllers; // 100 = 0x64
UIMoreListCellLayoutManager* _layoutManager; // 104 = 0x68
class-dump-? -a -C UIMoreListController UIKit
Generating ivar offsets by accumulation is a tricky business, due to alignments and bitfield packing. It is so tricky that the compiler will generate this info into the file. class-dump-z will read from that part of memory and give the most correct result.
Struct name prettifying
| | UIScrollView
3.0 |
|:|:-------------------|
| class-dump-x 3.1.2 | -(id)hitTest:(struct CGPoint)fp8 forEvent:(struct __GSEvent *)fp16;
|
| class-dump 3.3.1 | -(id)hitTest:(struct CGPoint)arg1 forEvent:(struct __GSEvent *)arg2;
|
| class-dump-z 0.2-0 | -(id)hitTest:(CGPoint)test forEvent:(GSEventRef)event;
|
class-dump-? -C UIScrollView -f hitTest UIKit
class-dump-z will typedef
structs and unions to the most presentable name with heuristics.
This feature can be explicitly turned off with the -N switch.
Stable name generation for anonymous structs
| | UIThreePartImageView
2.0 | UIThreePartImageView
3.0 |
|:|:---------------------------|:---------------------------|
| class-dump-x 3.1.2 | -(void)setSlices:(CDAnonymousStruct8)fp8;
| -(void)setSlices:(CDAnonymousStruct10)fp8;
|
| class-dump 3.3.1 | -(void)setSlices:(CDStruct_75b8db5d)arg1;
| -(void)setSlices:(CDStruct_75b8db5d)arg1;
|
| class-dump-z 0.2-0 | -(void)setSlices:(XXStruct_UUz0SD)slices;
| -(void)setSlices:(XXStruct_UUz0SD)slices;
|
class-dump-? -C UIThreePartImageView UIKit
Ever tried to diff a library between two versions? You'll be frustrated by so many differences that are caused by a change of indices in anonymous structs. No more problem in class-dump-z — as long as the struct is having the same members, the generated name will be fixed.
The name is computed by the CRC-32 checksum of the Objective-C type encoding of the struct.
Properties
| | UIScrollView
3.0 |
|:|:-------------------|
| class-dump-x 3.1.2 | N/A |
| class-dump 3.3.1 | @property(nonatomic) struct CGPoint contentOffset;
|
| class-dump-z 0.1-11o | @property(assign, nonatomic) CGPoint contentOffset;
|
class-dump-? -C UIScrollView UIKit
class-dump-z supports declared properties. Not only that, it supports every property attributes, including the undocumented ones. Moreover, it will hide the extra copy of getters/setters if a property is present.
Propertization
Some libraries are written before the dot syntax was introduced or by some dot-syntax-haters, so you'll see a long list of getters/setters like
-(void)setTitle:(id)title;
-(id)title;
-(void)setSubtitle:(id)subtitle;
-(id)subtitle;
...
I found it pretty annoying. In class-dump-z you can supply the -p
switch to automatically convert them into
@property(retain) id title;
@property(retain) id subtitle;
...
Hide inherited and delegate methods
@interface UITableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
int _tableViewStyle;
id _keyboardSupport;
}
@property(retain, nonatomic) UITableView* tableView;
// inherited: -(id)init;
-(id)initWithStyle:(int)style;
// inherited: -(void)dealloc;
-(id)existingTableView;
// declared property getter: -(id)tableView;
// declared property setter: -(void)setTableView:(id)view;
// inherited: -(void)loadView;
// inherited: -(void)viewWillAppear:(BOOL)view;
// inherited: -(void)viewWillDisappear:(BOOL)view;
// inherited: -(void)viewDidAppear:(BOOL)view;
-(void)setEditing:(BOOL)editing animated:(BOOL)animated;
-(void)_adjustTableForKeyboardInfo:(id)keyboardInfo;
// in a protocol: -(int)tableView:(id)view numberOfRowsInSection:(int)section;
// in a protocol: -(id)tableView:(id)view cellForRowAtIndexPath:(id)indexPath;
// in a protocol: -(void)tableView:(id)view willBeginEditingRowAtIndexPath:(id)indexPath;
// in a protocol: -(void)tableView:(id)view didEndEditingRowAtIndexPath:(id)indexPath;
@end
Method overloading in subclass is very common in OO design, but such information is useless when generating headers. Yet, by default a class dumper wouldn't know if an implementation is overloaded or a new method. If it's not useful, why not hide them? class-dump-z does that.
Another class of useless information are those being implemented to adopt a protocol. class-dump-z can also filter them out.
If you are running class-dump-z outside of the iPhoneOS, or you haven't installed the SDK, you have to tell class-dump-z where can the libraries be found by the -y switch. If you using using firmware 3.1, because all framework binaries are removed, hiding inherited methods from external frameworks won't work properly.
Readable argument names
| | UIImage(UIImageDeprecated)
3.0 |
|:|:---------------------------------|
| class-dump-x 3.1.2 | -(void)draw9PartImageWithSliceRects:(CDAnonymousStruct13)fp8 inRect:(struct CGRect)fp152;
|
| class-dump 3.3.1 | -(void)draw9PartImageWithSliceRects:(CDStruct_c8cd2c5d)arg1 inRect:(struct CGRect)arg2;
|
| class-dump-z 0.2-0 | -(void)draw9PartImageWithSliceRects:(XXStruct_4cr1oD)sliceRects inRect:(CGRect)rect;
|
class-dump-? -C UIImageDeprecated UIKit
No more meaningless fpXX. class-dump-z will give a suitable name to each argument using Apple's coding style guide.
Correct header generation
| | WebThreadSafeUndoManager
3.1 |
|:|:-------------------------------|
| class-dump-x 3.1.2 | #import "NSUndoManager.h"
|
| class-dump 3.3.1 | #import "NSUndoManager.h"
|
| class-dump-z 0.2-0 | #import <Foundation/NSUndoManager.h>
|
The headers generated by -H
are not immediately usable because the imports usually points to non-existing .h files. There is even a page dedicated to fixing this problem.
class-dump-z now will see which library the external class comes from, and tries to make up a better .h file location to import.
Even with this change, headers generated by class-dump-z is generally not immediately usable either. This is usually because of name clash with Foundation and CoreFoundation objects. Most of the cases supplying the
-X NS,CF
flag to filter them out is enough to fix it.
Hints file
When an Objective-C source is compiled, the class name in a method will be stripped, so in the dump you'll get
-(void)touchesBegan:(id)began withEvent:(id)event;
instead of
-(void)touchesBegan:(NSSet*)began withEvent:(UIEvent*)event;
Hints file is created to address this problem. When you pass the -i
flag, a tab-delimited file will be created, which contains the type signature e.g.
-[UIGestureRecognizer touchesBegan:withEvent:] void id id
You can edit this file and change to the more precise signature, i.e.
-[UIGestureRecognizer touchesBegan:withEvent:] void NSSet* UIEvent*
then feed the same file with the -i
flag. The updated signature will be reflected in the dump.
Miscellaneous features
- Class attributes, e.g.
__attribute__((visibility("hidden")))
. - Supports obscure type encodings, e.g. the C99
_Complex
types, Objective-C class ivars with ≥2 protocols, GC-invisible pointers, etc. - Put that star on the left or right, I like
int* x
more, some people likeint *x
more. With the-R
switch one can switch between the two styles easily. - Put a space or not after the +/-. With the
-b
switch one can choose to use- (void)hello
or-(void)hello
.
What's missing
There are some features I don't find them immediately useful, so they are not supported yet.
Sort by inheritance (-I flag), Recursive dumping (-r)
These are not easy to implement and I find them not so useful so I left them out.