| 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
|
|
|
|
|