Index: class-dump/src/CDSymbol.m |
=================================================================== |
--- class-dump/src/CDSymbol.m (revision 0) |
+++ class-dump/src/CDSymbol.m (revision 0) |
@@ -0,0 +1,270 @@ |
+// -*- mode: ObjC -*- |
+ |
+// This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files. |
+// Copyright (C) 1997-1998, 2000-2001, 2004-2010 Steve Nygard. |
+ |
+#import "CDSymbol.h" |
+ |
+#import <mach-o/nlist.h> |
+#import <mach-o/loader.h> |
+#import "CDMachOFile.h" |
+#import "CDLCDylib.h" |
+#import "CDLCSegment.h" |
+#import "CDSection.h" |
+ |
+NSString *const ObjCClassSymbolPrefix = @"_OBJC_CLASS_$_"; |
+ |
+@implementation CDSymbol |
+ |
+- (id)initWithName:(NSString *)aName machOFile:(CDMachOFile *)aMachOFile nlist32:(struct nlist)nlist32; |
+{ |
+ if ([super init] == nil) |
+ return nil; |
+ |
+ is32Bit = YES; |
+ name = [aName retain]; |
+ nonretained_machOFile = aMachOFile; |
+ nlist.n_un.n_strx = 0; // We don't use it. |
+ nlist.n_type = nlist32.n_type; |
+ nlist.n_sect = nlist32.n_sect; |
+ nlist.n_desc = nlist32.n_desc; |
+ nlist.n_value = nlist32.n_value; |
+ |
+ return self; |
+} |
+ |
+- (id)initWithName:(NSString *)aName machOFile:(CDMachOFile *)aMachOFile nlist64:(struct nlist_64)nlist64; |
+{ |
+ if ([super init] == nil) |
+ return nil; |
+ |
+ is32Bit = NO; |
+ name = [aName retain]; |
+ nonretained_machOFile = aMachOFile; |
+ nlist.n_un.n_strx = 0; // We don't use it. |
+ nlist.n_type = nlist64.n_type; |
+ nlist.n_sect = nlist64.n_sect; |
+ nlist.n_desc = nlist64.n_desc; |
+ nlist.n_value = nlist64.n_value; |
+ |
+ return self; |
+} |
+ |
+- (void)dealloc; |
+{ |
+ [name release]; |
+ |
+ [super dealloc]; |
+} |
+ |
+- (uint64_t)value; |
+{ |
+ return nlist.n_value; |
+} |
+ |
+- (NSString *)name; |
+{ |
+ return name; |
+} |
+ |
+- (CDSection *)section |
+{ |
+ // We might be tempted to do [[nonretained_machOFile segmentContainingAddress:nlist.n_value] sectionContainingAddress:nlist.n_value] |
+ // but this does not work for __mh_dylib_header for example (n_value == 0, but it is in the __TEXT,__text section) |
+ NSMutableArray *sections = [NSMutableArray array]; |
+ for (CDLCSegment *segment in [nonretained_machOFile segments]) { |
+ for (CDSection *section in [segment sections]) |
+ [sections addObject:section]; |
+ } |
+ |
+ // n_sect is 1-indexed (NO_SECT == 0) |
+ NSUInteger sectionIndex = nlist.n_sect - 1; |
+ if (sectionIndex < [sections count]) |
+ return [sections objectAtIndex:sectionIndex]; |
+ else |
+ return nil; |
+} |
+ |
+- (CDLCDylib *)dylibLoadCommand; |
+{ |
+ NSUInteger libraryOrdinal = GET_LIBRARY_ORDINAL(nlist.n_desc); |
+ NSArray *dylibLoadCommands = [nonretained_machOFile dylibLoadCommands]; |
+ |
+ if (libraryOrdinal < [dylibLoadCommands count]) |
+ return [dylibLoadCommands objectAtIndex:libraryOrdinal]; |
+ else |
+ return nil; |
+} |
+ |
+- (BOOL)isExternal; |
+{ |
+ return (nlist.n_type & N_EXT) == N_EXT; |
+} |
+ |
+- (BOOL)isPrivateExternal; |
+{ |
+ return (nlist.n_type & N_PEXT) == N_PEXT; |
+} |
+ |
+- (NSUInteger)stab; |
+{ |
+ return nlist.n_type & N_STAB; |
+} |
+ |
+- (NSUInteger)type; |
+{ |
+ return nlist.n_type & N_TYPE; |
+} |
+ |
+- (BOOL)isUndefined; |
+{ |
+ return [self type] == N_UNDF; |
+} |
+ |
+- (BOOL)isAbsolte; |
+{ |
+ return [self type] == N_ABS; |
+} |
+ |
+- (BOOL)isInSection; |
+{ |
+ return [self type] == N_SECT; |
+} |
+ |
+- (BOOL)isPrebound; |
+{ |
+ return [self type] == N_PBUD; |
+} |
+ |
+- (BOOL)isIndirect; |
+{ |
+ return [self type] == N_INDR; |
+} |
+ |
+- (BOOL)isCommon; |
+{ |
+ return [self isUndefined] && [self isExternal] && nlist.n_value != 0; |
+} |
+ |
+- (BOOL)isInTextSection; |
+{ |
+ CDSection *section = [self section]; |
+ return [[section segmentName] isEqualToString:@"__TEXT"] && [[section sectionName] isEqualToString:@"__text"]; |
+} |
+ |
+- (BOOL)isInDataSection; |
+{ |
+ CDSection *section = [self section]; |
+ return [[section segmentName] isEqualToString:@"__DATA"] && [[section sectionName] isEqualToString:@"__data"]; |
+} |
+ |
+- (BOOL)isInBssSection; |
+{ |
+ CDSection *section = [self section]; |
+ return [[section segmentName] isEqualToString:@"__DATA"] && [[section sectionName] isEqualToString:@"__bss"]; |
+} |
+ |
+- (NSUInteger)referenceType; |
+{ |
+ return (nlist.n_desc & REFERENCE_TYPE); |
+} |
+ |
+- (NSString *)referenceTypeName |
+{ |
+ switch ([self referenceType]) { |
+ case REFERENCE_FLAG_UNDEFINED_NON_LAZY: return @"undefined non lazy"; |
+ case REFERENCE_FLAG_UNDEFINED_LAZY: return @"undefined lazy"; |
+ case REFERENCE_FLAG_DEFINED: return @"defined"; |
+ case REFERENCE_FLAG_PRIVATE_DEFINED: return @"private defined"; |
+ case REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY: return @"private undefined non lazy"; |
+ case REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY: return @"private undefined lazy"; |
+ } |
+ return nil; |
+} |
+ |
+- (NSComparisonResult)compare:(CDSymbol *)aSymbol; |
+{ |
+ if ([aSymbol value] > [self value]) |
+ return NSOrderedAscending; |
+ else if ([aSymbol value] < [self value]) |
+ return NSOrderedDescending; |
+ else |
+ return NSOrderedSame; |
+} |
+ |
+- (NSComparisonResult)nameCompare:(CDSymbol *)aSymbol; |
+{ |
+ return [[self name] compare:[aSymbol name]]; |
+} |
+ |
+- (NSString *)shortTypeDescription; |
+{ |
+ NSString *c = nil; |
+ |
+ if ([self stab]) |
+ c = @"-"; |
+ else if ([self isCommon]) |
+ c = @"c"; |
+ else if ([self isUndefined] || [self isPrebound]) |
+ c = @"u"; |
+ else if ([self isAbsolte]) |
+ c = @"a"; |
+ else if ([self isInSection]) { |
+ if ([self isInTextSection]) |
+ c = @"t"; |
+ else if ([self isInDataSection]) |
+ c = @"d"; |
+ else if ([self isInBssSection]) |
+ c = @"b"; |
+ else |
+ c = @"s"; |
+ } |
+ else if ([self isIndirect]) |
+ c = @"i"; |
+ else |
+ c = @"?"; |
+ |
+ return [self isExternal] ? [c uppercaseString] : c; |
+} |
+ |
+- (NSString *)longTypeDescription; |
+{ |
+ NSString *c = nil; |
+ |
+ if ([self isCommon]) |
+ c = @"common"; |
+ else if ([self isUndefined]) |
+ c = @"undefined"; |
+ else if ([self isPrebound]) |
+ c = @"prebound"; |
+ else if ([self isAbsolte]) |
+ c = @"absolute"; |
+ else if ([self isInSection]) { |
+ CDSection *section = [self section]; |
+ if (section) |
+ c = [NSString stringWithFormat:@"%@,%@", [section segmentName], [section sectionName]]; |
+ else |
+ c = @"?,?"; |
+ } |
+ else if ([self isIndirect]) |
+ c = @"indirect"; |
+ else |
+ c = @"?"; |
+ |
+ return c; |
+} |
+ |
+- (NSString *)description; |
+{ |
+ NSString *valueFormat = [NSString stringWithFormat:@"%%0%ullx", is32Bit ? 8 : 16]; |
+ NSString *valuePad = is32Bit ? @" " : @" "; |
+ NSString *valueString = [self isUndefined] ? valuePad : [NSString stringWithFormat:valueFormat, [self value]]; |
+ NSString *dylibName = [[[[[self dylibLoadCommand] path] lastPathComponent] componentsSeparatedByString:@"."] objectAtIndex:0]; |
+ NSString *fromString = [self isUndefined] ? [NSString stringWithFormat:@" (from %@)", dylibName] : @""; |
+ return [NSString stringWithFormat:@"%@ %@ %@", valueString, [self shortTypeDescription], name]; |
+ return [NSString stringWithFormat:@"%@ (%@) %@ %@%@", valueString, [self longTypeDescription], [self isExternal] ? @"external" : @"non-external", name, fromString]; |
+ return [NSString stringWithFormat:[valueFormat stringByAppendingString:@" %02x %02x %04x - %@"], |
+ nlist.n_value, nlist.n_type, nlist.n_sect, nlist.n_desc, name]; |
+} |
+ |
+@end |
Property changes on: class-dump/src/CDSymbol.m |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |