class-dump: Dumping Classes
class-dump path_to_executable
If the tool nm and its wealth of information seems impressive, class-dump is amazing. Feed it an executable and get back a complete list of class names, internal variables, and methods, even as a set of header files, thanks to its deep understanding of Objective-C and Mach-O. Apple’s product might be stripped of their symbols, but class-dump can list their internal structure.
I created a template application, added a method (shouldShowInClassDump), and built it with all the symbols stripped out. Running class-dump on the resulting Release executable revealed the following:
/*
* Generated by class-dump 3.3.1 (64 bit).
*
* class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2009 by Steve Nygard.
*/
#pragma mark -
/*
* File: build/Release/SampleApp.app/Contents/MacOS/SampleApp
* Arch: Intel x86-64 (x86_64)
*
* Objective-C Garbage Collection: Unsupported
*/
@interface SampleAppAppDelegate : NSObject
{
NSWindow *window;
}
- (void)applicationDidFinishLaunching:(id)arg1;
- (BOOL)shouldShowInClassDump:(id)arg1;
@property NSWindow *window; // @synthesize window;
@end
To see how applications compared in aggregate, I wrote a simple ruby script to walk through /Applications and sum up the number of lines of headers from class-dump and the number of @interface declarations. Both are crude measures of complexity.
Top 10 by Header Lines
37968 iPhoto 37053 Aperture 21228 iWeb 19307 Keynote 16564 iMovie 16235 Coda 15625 Keynote 15111 Grapher 14735 Pages 14724 iCal
Top 10 by Interfaces
1203 Aperture 1066 iWeb 1004 Grapher 967 iPhoto 859 Path Finder 748 Keynote 730 iMovie 664 LaunchBar 649 iCal 646 Coda
Top 10 by Lines Per Interface
39.54 Retrospect 39.33 Grab 39.26 iPhoto 37.72 MemoryMiner 37.28 Papers 35.72 iTunes 35.65 Sequel Pro 34.71 Console 32.72 iChat 32.38 GarageBand
Apple’s tools are clearly complex, with iPhoto and Aperture leading by almost a factor of two in header lines, but apps like Panic’s Coda hold their own. And Retrospect topping the final list is obviously an indictment of my coding abilities.
Ruby Script
#!/usr/local/bin/ruby19
# analyze_apps.rb
# * Analyze dump from 'class-dump path_to_executable' to collect statistics: Interfaces, Lines
# Collect app paths.
CLASS_DUMP_PATH = "/usr/local/bin/class-dump"
apps = []
apps_folders = ["/Applications", "/Applications/iWork '08", "/Applications/iWork '09", "/Applications/Microsoft Office 2004", "/Applications/Microsoft Office 2008", "/Applications/Utilities"]
apps_folders.each do |app_folder|
app_list = Dir.entries(app_folder)
app_list.each do |app|
apps << "#{app_folder}/#{app}"
end
end
# Loop through apps.
apps.each do |app|
# Check that the app exists.
if Dir.exists?("#{app}") && app.include?(".app")
app_array = app.split("/")
app_name = app_array[app_array.count-1].split(".app")[0]
exe_path = "#{app}/Contents/MacOS/#{app_name}"
# Check that the executable exists.
if File.exists?(exe_path)
# Use 'classdump' to dump Mach-O header information.
results = %x[#{CLASS_DUMP_PATH} "#{exe_path}"].split("\n")
line_count = results.count
interface_count = 0
results.each do |line|
if line.include?("@interface ")
interface_count = interface_count + 1
# puts "#{app_name}: #{line}"
end
end
puts "#{app_name},#{app},#{interface_count},#{line_count}"
end
end
end









3 Comments