bdunagan

fill the void - bdunagan

17 May 2010
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
Previous LinkedIn Twitter GitHub Email Next