home *** CD-ROM | disk | FTP | other *** search
- //
- // $Id: class-dump.m,v 1.9 1997/12/08 08:03:00 nygard Exp $
- //
-
- //
- // This file is a part of class-dump v2, a utility for examining the
- // Objective-C segment of Mach-O files.
- // Copyright (C) 1997 Steve Nygard
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation; either version 2 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program; if not, write to the Free Software
- // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- //
- // You may contact the author by:
- // e-mail: nygard@telusplanet.net
- //
-
- #include <stdio.h>
- #include <libc.h>
- #include <ctype.h>
-
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #include <mach/mach.h>
- #include <mach/mach_error.h>
-
- #include <mach-o/loader.h>
- #include <mach-o/fat.h>
-
- #if NS_TARGET_MAJOR >= 4
- #import <Foundation/Foundation.h>
- #else
- #import <foundation/NSString.h>
- #import <foundation/NSArray.h>
- #import <foundation/NSDictionary.h>
- #import <foundation/NSAutoreleasePool.h>
- #import <foundation/NSUtilities.h>
- #endif
-
- #include "datatypes.h"
- #include "class-dump.h"
-
- #include "my_regex.h"
-
- #import "ObjcThing.h"
- #import "ObjcClass.h"
- #import "ObjcCategory.h"
- #import "ObjcProtocol.h"
- #import "ObjcIvar.h"
- #import "ObjcMethod.h"
- #import "MappedFile.h"
-
- #ifndef LC_PREBOUND_DYLIB
- #define LC_PREBOUND_DYLIB 0x10
- #endif
-
- #ifndef LC_LOAD_DYLIB
- #define LC_LOAD_DYLIB 0x0c
-
- struct dylib {
- union lc_str name;
- unsigned long timestamp;
- unsigned long current_version;
- unsigned long compatibility_version;
- };
-
- struct dylib_command {
- unsigned long cmd;
- unsigned long cmdsize;
- struct dylib dylib;
- };
- #endif
-
- //----------------------------------------------------------------------
-
- #define CLASS_DUMP_VERSION "2.1.1"
-
- int expand_structures_flag = 0;
- int char_star_flag = 0;
-
- BOOL show_ivar_offsets_flag = NO;
- BOOL show_method_addresses_flag = NO;
- BOOL expand_protocols_flag = NO;
- BOOL match_flag = NO;
- BOOL expand_frameworks_flag = NO;
- BOOL sort_flag = NO;
-
- int swap_fat = 0;
- int swap_macho = 0;
-
- #define MAX_SECTIONS 2048
-
- NSMutableArray *mappedFiles;
-
- char *current_filename = NULL;
-
- struct section_info
- {
- char *filename;
- char name[17];
- struct section *section;
- void *start;
- long vmaddr;
- long size;
- } objc_sections[MAX_SECTIONS];
-
- int section_count = 0;
-
- //----------------------------------------------------------------------
-
- #define SEC_CLASS "__class"
- #define SEC_SYMBOLS "__symbols"
- #define SEC_PROTOCOL "__protocol"
- #define SEC_CATEGORY "__category"
- #define SEC_CLS_METH "__cls_meth"
- #define SEC_INST_METH "__inst_meth"
- #define SEC_META_CLASS "__meta_class"
- #define SEC_CLASS_NAMES "__class_names"
- #define SEC_MODULE_INFO "__module_info"
- #define SEC_CAT_CLS_METH "__cat_cls_meth"
- #define SEC_INSTANCE_VARS "__instance_vars"
- #define SEC_CAT_INST_METH "__cat_inst_meth"
- #define SEC_METH_VAR_TYPES "__meth_var_types"
- #define SEC_METH_VAR_NAMES "__meth_var_names"
-
- //======================================================================
-
- char *file_type_names[] =
- {
- "MH_<unknown>",
- "MH_OBJECT",
- "MH_EXECUTE",
- "MH_FVMLIB",
- "MH_CORE",
- "MH_PRELOAD",
- "MH_DYLIB",
- "MH_DYLINKER",
- "MH_BUNDLE",
- };
-
- char *load_command_names[] =
- {
- "LC_<unknown>",
- "LC_SEGMENT",
- "LC_SYMTAB",
- "LC_SYMSEG",
- "LC_THREAD",
- "LC_UNIXTHREAD",
- "LC_LOADFVMLIB",
- "LC_IDFVMLIB",
- "LC_IDENT",
- "LC_FVMFILE",
- "LC_PREPAGE",
- "LC_DYSYMTAB",
- "LC_LOAD_DYLIB",
- "LC_ID_DYLIB",
- "LC_LOAD_DYLINKER",
- "LC_ID_DYLINKER",
- "LC_PREBOUND_DYLIB",
- };
-
- NSMutableDictionary *protocols;
-
- //======================================================================
-
- void process_file (void *ptr, char *filename);
-
- int process_macho (void *ptr, char *filename);
- unsigned long process_load_command (void *start, void *ptr, char *filename);
- void process_dylib_command (void *start, void *ptr);
- void process_fvmlib_command (void *start, void *ptr);
- void process_segment_command (void *start, void *ptr, char *filename);
- void process_objc_segment (void *start, void *ptr, char *filename);
-
- struct section_info *find_objc_section (char *name, char *filename);
- void *translate_address_to_pointer (long addr, char *section);
- char *string_at (long addr, char *section);
- NSString *nsstring_at (long addr, char *section);
-
- struct section_info *section_of_address (long addr);
- NSArray *handle_objc_symtab (struct my_objc_symtab *symtab);
- ObjcClass *handle_objc_class (struct my_objc_class *ocl);
- ObjcCategory *handle_objc_category (struct my_objc_category *ocat);
- NSArray *handle_objc_protocols (struct my_objc_protocol_list *plist, BOOL expandProtocols);
- NSArray *handle_objc_meta_class (struct my_objc_class *ocl);
- NSArray *handle_objc_ivars (struct my_objc_ivars *ivars);
- NSArray *handle_objc_methods (struct my_objc_methods *methods, char ch);
-
- void show_single_module (struct section_info *module_info);
- void show_all_modules (void);
- void build_up_objc_segments (char *filename);
-
- //======================================================================
-
- void process_file (void *ptr, char *filename)
- {
- struct mach_header *mh = (struct mach_header *)ptr;
- struct fat_header *fh = (struct fat_header *)ptr;
- struct fat_arch *fa = (struct fat_arch *)(fh + 1);
- int l;
- int result = 1;
-
- if (mh->magic == FAT_CIGAM)
- {
- // Fat file... Other endian.
-
- swap_fat = 1;
- for (l = 0; l < NXSwapLong (fh->nfat_arch); l++)
- {
- #ifdef VERBOSE
- printf ("archs: %ld\n", NXSwapLong (fh->nfat_arch));
- printf ("offset: %lx\n", NXSwapLong (fa->offset));
- printf ("arch: %08lx\n", NXSwapLong (fa->cputype));
- #endif
- result = process_macho (ptr + NXSwapLong (fa->offset), filename);
- if (result == 0)
- break;
- fa++;
- }
- }
- else if (mh->magic == FAT_MAGIC)
- {
- // Fat file... This endian.
-
- for (l = 0; l < fh->nfat_arch; l++)
- {
- #ifdef VERBOSE
- printf ("archs: %ld\n", fh->nfat_arch);
- printf ("offset: %lx\n", fa->offset);
- printf ("arch: %08lx\n", fa->cputype);
- #endif
- result = process_macho (ptr + fa->offset, filename);
- if (result == 0)
- break;
- fa++;
- }
- }
- else
- {
- result = process_macho (ptr, filename);
- }
-
- switch (result)
- {
- case 0:
- break;
-
- case 1:
- printf ("Error: File did not contain an executable with our endian.\n");
- break;
-
- default:
- printf ("Error: processing Mach-O file.\n");
- }
- }
-
- //----------------------------------------------------------------------
-
- // Returns 0 if this was our endian, 1 if it was not, 2 otherwise.
-
- int process_macho (void *ptr, char *filename)
- {
- struct mach_header *mh = (struct mach_header *)ptr;
- int l;
- void *start = ptr;
-
- if (mh->magic == MH_CIGAM)
- {
- swap_macho = 1;
- return 1;
- }
- else if (mh->magic != MH_MAGIC)
- {
- printf ("This is not a Mach-O file.\n");
- return 2;
- }
-
- ptr += sizeof (struct mach_header);
-
- for (l = 0; l < mh->ncmds; l++)
- {
- ptr += process_load_command (start, ptr, filename);
- }
-
- return 0;
- }
-
- //----------------------------------------------------------------------
-
- unsigned long process_load_command (void *start, void *ptr, char *filename)
- {
- struct load_command *lc = (struct load_command *)ptr;
-
- #ifdef VERBOSE
- if (lc->cmd >= 0 && lc->cmd <= LC_PREBOUND_DYLIB)
- {
- printf ("%s\n", load_command_names[ lc->cmd ]);
- }
- else
- {
- printf ("%08lx\n", lc->cmd);
- }
- #endif
-
- if (lc->cmd == LC_SEGMENT)
- {
- process_segment_command (start, ptr, filename);
- }
- else if (lc->cmd == LC_LOAD_DYLIB)
- {
- process_dylib_command (start, ptr);
- }
- else if (lc->cmd == LC_LOADFVMLIB)
- {
- process_fvmlib_command (start, ptr);
- }
-
- return lc->cmdsize;
- }
-
- //----------------------------------------------------------------------
-
- void process_dylib_command (void *start, void *ptr)
- {
- struct dylib_command *dc = (struct dylib_command *)ptr;
-
- build_up_objc_segments (ptr + dc->dylib.name.offset);
- }
-
- //----------------------------------------------------------------------
-
- void process_fvmlib_command (void *start, void *ptr)
- {
- struct fvmlib_command *fc = (struct fvmlib_command *)ptr;
-
- build_up_objc_segments (ptr + fc->fvmlib.name.offset);
- }
-
- //----------------------------------------------------------------------
-
- void process_segment_command (void *start, void *ptr, char *filename)
- {
- struct segment_command *sc = (struct segment_command *)ptr;
- char name[17];
-
- strncpy (name, sc->segname, 16);
- name[16] = 0;
-
- if (!strcmp (name, SEG_OBJC))
- {
- process_objc_segment (start, ptr, filename);
- }
- }
-
- //----------------------------------------------------------------------
-
- void process_objc_segment (void *start, void *ptr, char *filename)
- {
- struct segment_command *sc = (struct segment_command *)ptr;
- struct section *section = (struct section *)(sc + 1);
- int l;
-
- for (l = 0; l < sc->nsects; l++)
- {
- if (section_count >= MAX_SECTIONS)
- {
- printf ("Error: Maximum number of sections reached.\n");
- return;
- }
-
- objc_sections[section_count].filename = filename;
- strncpy (objc_sections[section_count].name, section->sectname, 16);
- objc_sections[section_count].name[16] = 0;
- objc_sections[section_count].section = section;
- objc_sections[section_count].start = start + section->offset;
- objc_sections[section_count].vmaddr = section->addr;
- objc_sections[section_count].size = section->size;
- section++;
- section_count++;
- }
- }
-
- //----------------------------------------------------------------------
-
- // Find the Objective-C segment for the given filename noted in our
- // list.
-
- struct section_info *find_objc_section (char *name, char *filename)
- {
- int l;
-
- for (l = 0; l < section_count; l++)
- {
- if (!strcmp (name, objc_sections[l].name) && !strcmp (filename, objc_sections[l].filename))
- {
- return &objc_sections[l];
- }
- }
-
- return NULL;
- }
-
- //----------------------------------------------------------------------
-
- void debug_section_overlap (void)
- {
- int l;
-
- for (l = 0; l < section_count; l++)
- {
- printf ("%10ld to %10ld [size 0x%08ld] %-16s of %s\n",
- objc_sections[l].vmaddr, objc_sections[l].vmaddr + objc_sections[l].size, objc_sections[l].size,
- objc_sections[l].name, objc_sections[l].filename);
- }
- }
-
- //----------------------------------------------------------------------
-
- //
- // Take a long from the Mach-O file (which is really a pointer when
- // the section is loaded at the proper location) and translate it into
- // a pointer to where we have the file mapped.
- //
-
- void *translate_address_to_pointer (long addr, char *section)
- {
- int l;
- int count = 0;
-
- for (l = 0; l < section_count; l++)
- {
- if (addr >= objc_sections[l].vmaddr && addr < objc_sections[l].vmaddr + objc_sections[l].size
- && !strcmp (objc_sections[l].name, section))
- {
- count++;
- }
- }
-
- if (count > 1)
- {
- // If there are still duplicates, we choose the one for the current file.
- for (l = 0; l < section_count; l++)
- {
- if (addr >= objc_sections[l].vmaddr && addr < objc_sections[l].vmaddr + objc_sections[l].size
- && !strcmp (objc_sections[l].name, section)
- && !strcmp (objc_sections[l].filename, current_filename))
- {
- return objc_sections[l].start + addr - objc_sections[l].vmaddr;
- }
- }
- }
- else
- {
- for (l = 0; l < section_count; l++)
- {
- if (addr >= objc_sections[l].vmaddr && addr < objc_sections[l].vmaddr + objc_sections[l].size
- && !strcmp (objc_sections[l].name, section))
- {
- return objc_sections[l].start + addr - objc_sections[l].vmaddr;
- }
- }
- }
-
- if (addr != 0)
- printf ("address (0x%08lx) not in OBJC segment!\n", addr);
-
- return NULL;
- }
-
- //----------------------------------------------------------------------
-
- char *string_at (long addr, char *section)
- {
- return (char *)translate_address_to_pointer (addr, section);
- }
-
- //----------------------------------------------------------------------
-
- NSString *nsstring_at (long addr, char *section)
- {
- char *str = string_at (addr, section);
- return (str == NULL) ? (NSString *)@"" : [NSString stringWithCString:str];
- }
-
- //----------------------------------------------------------------------
-
- struct section_info *section_of_address (long addr)
- {
- int l;
-
- for (l = 0; l < section_count; l++)
- {
- if (addr >= objc_sections[l].vmaddr && addr < objc_sections[l].vmaddr + objc_sections[l].size)
- {
- return &objc_sections[l];
- }
- }
-
- return NULL;
- }
-
- //======================================================================
-
- NSArray *handle_objc_symtab (struct my_objc_symtab *symtab)
- {
- NSMutableArray *classList = [NSMutableArray array];
- ObjcThing *objcThing;
- long *class_pointer;
- int l;
-
- if (symtab == NULL)
- {
- printf ("NULL symtab...\n");
- return nil;
- }
-
- class_pointer = &symtab->class_pointer;
-
- for (l = 0; l < symtab->cls_def_count; l++)
- {
- objcThing = handle_objc_class (translate_address_to_pointer (*class_pointer, SEC_CLASS));
- if (objcThing != nil)
- [classList addObject:objcThing];
-
- class_pointer++;
- }
-
- for (l = 0; l < symtab->cat_def_count; l++)
- {
- objcThing = handle_objc_category (translate_address_to_pointer (*class_pointer, SEC_CATEGORY));
- if (objcThing != nil)
- [classList addObject:objcThing];
-
- class_pointer++;
- }
-
- return classList;
- }
-
- //----------------------------------------------------------------------
-
- ObjcClass *handle_objc_class (struct my_objc_class *ocl)
- {
- ObjcClass *objcClass;
- NSArray *tmp;
-
- if (ocl == NULL)
- return nil;
-
- tmp = handle_objc_protocols ((struct my_objc_protocol_list *)translate_address_to_pointer (ocl->protocols, SEC_CAT_CLS_METH), YES);
-
- if (string_at (ocl->super_class, SEC_CLASS_NAMES) == NULL)
- {
- objcClass = [[[ObjcClass alloc] initWithClassName:nsstring_at (ocl->name, SEC_CLASS_NAMES) superClassName:nil] autorelease];
- }
- else
- {
- objcClass = [[[ObjcClass alloc] initWithClassName:nsstring_at (ocl->name, SEC_CLASS_NAMES)
- superClassName:nsstring_at (ocl->super_class, SEC_CLASS_NAMES)] autorelease];
- }
-
- [objcClass addProtocolNames:tmp];
-
- tmp = handle_objc_ivars ((struct my_objc_ivars *)translate_address_to_pointer (ocl->ivars, SEC_INSTANCE_VARS));
- [objcClass addIvars:tmp];
-
- tmp = handle_objc_meta_class ((struct my_objc_class *)translate_address_to_pointer (ocl->isa, SEC_META_CLASS));
- [objcClass addClassMethods:tmp];
-
- tmp = handle_objc_methods ((struct my_objc_methods *)translate_address_to_pointer (ocl->methods, SEC_INST_METH), '-');
- [objcClass addInstanceMethods:tmp];
-
- return objcClass;
- }
-
- //----------------------------------------------------------------------
-
- ObjcCategory *handle_objc_category (struct my_objc_category *ocat)
- {
- ObjcCategory *objcCategory;
- NSArray *tmp;
-
- if (ocat == NULL)
- return nil;
-
- objcCategory = [[[ObjcCategory alloc] initWithClassName:nsstring_at (ocat->class_name, SEC_CLASS_NAMES)
- categoryName:nsstring_at (ocat->category_name, SEC_CLASS_NAMES)] autorelease];
-
- tmp = handle_objc_methods ((struct my_objc_methods *)translate_address_to_pointer (ocat->class_methods, SEC_CAT_CLS_METH), '+');
- [objcCategory addClassMethods:tmp];
-
- tmp = handle_objc_methods ((struct my_objc_methods *)translate_address_to_pointer (ocat->methods, SEC_CAT_INST_METH), '-');
- [objcCategory addInstanceMethods:tmp];
-
- return objcCategory;
- }
-
- //----------------------------------------------------------------------
-
- // Return list of protocol names.
- NSArray *handle_objc_protocols (struct my_objc_protocol_list *plist, BOOL expandProtocols)
- {
- NSMutableArray *protocolArray = [NSMutableArray array];
- ObjcProtocol *objcProtocol;
- struct my_objc_protocol *prot;
- struct my_objc_prot_inst_meth_list *mlist;
- struct my_objc_prot_inst_meth *meth;
- int l, p;
- long *ptr;
- NSArray *parentProtocols;
-
- if (plist == NULL)
- return nil;
-
- ptr = &plist->list;
-
- for (p = 0; p < plist->count; p++)
- {
- prot = translate_address_to_pointer (*ptr, SEC_PROTOCOL);
-
- objcProtocol = [[[ObjcProtocol alloc] initWithProtocolName:nsstring_at (prot->protocol_name, SEC_CLASS_NAMES)] autorelease];
- [protocolArray addObject:[objcProtocol protocolName]];
-
- parentProtocols = handle_objc_protocols (translate_address_to_pointer (prot->protocol_list, SEC_CAT_CLS_METH),
- expand_protocols_flag);
- [objcProtocol addProtocolNames:parentProtocols];
-
- mlist = translate_address_to_pointer (prot->instance_methods, SEC_CAT_INST_METH);
- if (mlist != NULL)
- {
- meth = (struct my_objc_prot_inst_meth *)&mlist->methods;
-
- for (l = 0; l < mlist->count; l++)
- {
- [objcProtocol addProtocolMethod:[[[ObjcMethod alloc] initWithMethodName:nsstring_at (meth->name, SEC_METH_VAR_NAMES)
- type:nsstring_at (meth->types, SEC_METH_VAR_TYPES)] autorelease]];
- meth++;
- }
- }
-
- if (expandProtocols == YES && [protocols objectForKey:[objcProtocol protocolName]] == nil)
- {
- [protocols setObject:objcProtocol forKey:[objcProtocol protocolName]];
- objcProtocol = nil;
- }
-
- ptr++;
- }
-
- return protocolArray;
- }
-
- //----------------------------------------------------------------------
-
- NSArray *handle_objc_meta_class (struct my_objc_class *ocl)
- {
- if (ocl == NULL)
- return nil;
-
- return handle_objc_methods ((struct my_objc_methods *)translate_address_to_pointer (ocl->methods, SEC_CLS_METH), '+');
- }
-
- //----------------------------------------------------------------------
-
- NSArray *handle_objc_ivars (struct my_objc_ivars *ivars)
- {
- struct my_objc_ivar *ivar = (struct my_objc_ivar *)(ivars + 1);
- NSMutableArray *ivarArray = [NSMutableArray array];
- ObjcIvar *objcIvar;
- int l;
-
- if (ivars == NULL)
- return nil;
-
- for (l = 0; l < ivars->ivar_count; l++)
- {
- objcIvar = [[[ObjcIvar alloc] initWithName:nsstring_at (ivar->name, SEC_METH_VAR_NAMES)
- type:nsstring_at (ivar->type, SEC_METH_VAR_TYPES)
- offset:ivar->offset] autorelease];
- [ivarArray addObject:objcIvar];
-
- ivar++;
- }
-
- return ivarArray;
- }
-
- //----------------------------------------------------------------------
-
- NSArray *handle_objc_methods (struct my_objc_methods *methods, char ch)
- {
- struct my_objc_method *method = (struct my_objc_method *)(methods + 1);
- NSMutableArray *methodArray = [NSMutableArray array];
- ObjcMethod *objcMethod;
- int l;
-
- if (methods == NULL)
- return nil;
-
- for (l = 0; l < methods->method_count; l++)
- {
- if (method->imp != 0)
- {
- objcMethod = [[[ObjcMethod alloc] initWithMethodName:nsstring_at (method->name, SEC_METH_VAR_NAMES)
- type:nsstring_at (method->types, SEC_METH_VAR_TYPES)
- address:method->imp] autorelease];
- [methodArray addObject:objcMethod];
- }
- method++;
- }
-
- return methodArray;
- }
-
- //======================================================================
-
- void show_single_module (struct section_info *module_info)
- {
- struct my_objc_module *m;
- int module_count;
- int l;
- char *tmp;
- id en, thing, key;
- NSMutableArray *classList = [NSMutableArray array];
- NSArray *newClasses;
- int flags = 0;
-
- if (module_info == NULL)
- {
- return;
- }
-
- if (sort_flag == YES)
- flags |= F_SORT_METHODS;
-
- if (show_ivar_offsets_flag == YES)
- flags |= F_SHOW_IVAR_OFFSET;
-
- if (show_method_addresses_flag == YES)
- flags |= F_SHOW_METHOD_ADDRESS;
-
- tmp = current_filename;
- m = module_info->start;
- module_count = module_info->size / sizeof (struct my_objc_module);
-
- printf ("\n/*\n * File: %s\n */\n\n", module_info->filename);
- current_filename = module_info->filename;
-
- for (l = 0; l < module_count; l++)
- {
- newClasses = handle_objc_symtab ((struct my_objc_symtab *)translate_address_to_pointer (m->symtab, SEC_SYMBOLS));
- [classList addObjectsFromArray:newClasses];
- m++;
- }
-
-
- if (sort_flag == YES)
- en = [[[protocols allKeys] sortedArrayUsingSelector:@selector (compare:)] objectEnumerator];
- else
- en = [[protocols allKeys] objectEnumerator];
-
- while (key = [en nextObject])
- {
- thing = [protocols objectForKey:key];
- if (match_flag == NO || RE_EXEC ([[thing sortableName] cString]) == 1)
- [thing showDefinition:flags];
- }
-
- if (sort_flag == YES)
- en = [[classList sortedArrayUsingSelector:@selector (orderByName:)] objectEnumerator];
- else
- en = [classList objectEnumerator];
-
- while (thing = [en nextObject])
- {
- if (match_flag == NO || RE_EXEC ([[thing sortableName] cString]) == 1)
- [thing showDefinition:flags];
- }
-
- [protocols removeAllObjects];
-
- current_filename = tmp;
- }
-
- //----------------------------------------------------------------------
-
- void show_all_modules (void)
- {
- int l;
-
- for (l = section_count - 1; l >= 0; l--)
- {
- if (!strcmp (objc_sections[l].name, SEC_MODULE_INFO))
- {
- show_single_module ((struct section_info *)&objc_sections[l]);
- }
- }
- }
-
- //----------------------------------------------------------------------
-
- void build_up_objc_segments (char *filename)
- {
- MappedFile *mappedFile;
- NSEnumerator *mfEnumerator;
-
- // Only process each file once.
-
- mfEnumerator = [mappedFiles objectEnumerator];
- while (mappedFile = [mfEnumerator nextObject])
- {
- if (!strcmp (filename, [[mappedFile filename] cString]))
- return;
- }
-
- mappedFile = [[[MappedFile alloc] initWithFilename:[NSString stringWithCString:filename]] autorelease];
- //NSCAssert (mappedFile != nil, @"Could not map file...");
- if (mappedFile != nil)
- {
- [mappedFiles addObject:mappedFile];
-
- process_file ((void *)[mappedFile data], filename);
- }
- }
-
- //----------------------------------------------------------------------
-
- void print_usage (void)
- {
- fprintf (stderr,
- "class-dump %s\n"
- "Usage: class-dump [-a] [-A] [-e] [-R] [-C regex] [-r] [-s] [-S] executable-file\n"
- " -a show instance variable offsets\n"
- " -A show implementation addresses\n"
- " -e expand structure (and union) definition whenever possible\n"
- " -R recursively expand @protocol <>\n"
- " -C only display classes matching regular expression\n"
- " -r recursively expand frameworks and fixed VM shared libraries\n"
- " -s convert STR to char *\n"
- " -S sort protocols, classes, and methods\n",
- CLASS_DUMP_VERSION
- );
- }
-
- //----------------------------------------------------------------------
-
- void print_header (void)
- {
- printf (
- "/*\n"
- " * Generated by class-dump (version %s).\n"
- " *\n"
- " * class-dump is Copyright (C) 1997 by Steve Nygard.\n"
- " */\n", CLASS_DUMP_VERSION
- );
- }
-
- //======================================================================
-
- int main (int argc, char *argv[])
- {
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- int c;
- extern int optind;
- extern char *optarg;
- int error_flag = 0;
- const char *tmp;
-
- if (argc == 1)
- {
- print_usage();
- exit (2);
- }
-
- while ( (c = getopt (argc, argv, "aAeRC:rsS")) != EOF)
- {
- switch (c)
- {
- case 'a':
- show_ivar_offsets_flag = YES;
- break;
-
- case 'A':
- show_method_addresses_flag = YES;
- break;
-
- case 'e':
- expand_structures_flag = 1;
- break;
-
- case 'R':
- expand_protocols_flag = YES;
- break;
-
- case 'C':
- if (match_flag == YES)
- {
- printf ("Error: sorry, only one -C allowed\n");
- error_flag++;
- }
- else
- {
- match_flag = YES;
-
- tmp = RE_COMP (optarg);
- if (tmp != NULL)
- {
- printf ("Error: %s\n", tmp);
- exit (1);
- }
- }
- break;
-
- case 'r':
- expand_frameworks_flag = YES;
- break;
-
- case 's':
- char_star_flag = 1;
- break;
-
- case 'S':
- sort_flag = YES;
- break;
-
- case '?':
- default:
- error_flag++;
- break;
- }
- }
-
- if (error_flag > 0)
- {
- print_usage ();
- exit (2);
- }
-
- mappedFiles = [NSMutableArray array];
- protocols = [NSMutableDictionary dictionary];
-
- if (optind < argc)
- {
- build_up_objc_segments (argv[optind]);
-
- print_header ();
-
- //debug_section_overlap ();
-
- if (section_count > 0)
- {
- if (expand_frameworks_flag == NO)
- show_single_module ((struct section_info *)find_objc_section (SEC_MODULE_INFO, argv[optind]));
- else
- show_all_modules ();
- }
- }
-
- [mappedFiles removeAllObjects];
-
- [pool release];
-
- return 0;
- }
-