blob: ef5093b778017a8031d8aa10821b6d81f92baa8a [file] [log] [blame]
// 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-2007 Steve Nygard
#import "CDSegmentCommand.h"
#include <mach-o/swap.h>
#import <Foundation/Foundation.h>
#import "CDFatFile.h"
#import "CDMachOFile.h"
#import "CDSection.h"
@implementation CDSegmentCommand
- (id)initWithPointer:(const void *)ptr machOFile:(CDMachOFile *)aMachOFile;
{
char buf[17];
if ([super initWithPointer:ptr machOFile:aMachOFile] == nil)
return nil;
segmentCommand = *(struct segment_command *)ptr;
if ([aMachOFile hasDifferentByteOrder] == YES)
swap_segment_command(&segmentCommand, CD_THIS_BYTE_ORDER);
memcpy(buf, segmentCommand.segname, 16);
buf[16] = 0;
name = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
// Is segmentCommand->segname always going to be NULL terminated?
//name = [[NSString alloc] initWithBytes:segmentCommand->segname length:strlen(segmentCommand->segname) encoding:NSASCIIStringEncoding];
[self _processSectionsWithPointer:ptr + sizeof(struct segment_command)];
return self;
}
- (void)_processSectionsWithPointer:(const void *)ptr;
{
NSMutableArray *sects;
int count, index;
// PRECONDITION: sections == nil
// POSTCONDITION: sections != nil
sects = [[NSMutableArray alloc] init];
count = segmentCommand.nsects;
for (index = 0; index < count; index++) {
CDSection *section;
section = [[CDSection alloc] initWithPointer:ptr segment:self];
[sects addObject:section];
[section release];
ptr += sizeof(struct section);
}
sections = [[NSArray alloc] initWithArray:sects];
[sects release];
}
- (void)dealloc;
{
[name release];
[sections release];
[super dealloc];
}
- (NSString *)name;
{
return name;
}
- (unsigned long)vmaddr;
{
return segmentCommand.vmaddr;
}
- (unsigned long)fileoff;
{
return segmentCommand.fileoff;
}
- (unsigned long)flags;
{
return segmentCommand.flags;
}
- (NSArray *)sections;
{
return sections;
}
- (BOOL)isProtected;
{
return (segmentCommand.flags & SG_PROTECTED_VERSION_1) == SG_PROTECTED_VERSION_1;
}
- (NSString *)flagDescription;
{
NSMutableArray *setFlags;
unsigned long flags;
setFlags = [NSMutableArray array];
flags = [self flags];
if (flags & SG_HIGHVM)
[setFlags addObject:@"HIGHVM"];
if (flags & SG_FVMLIB)
[setFlags addObject:@"FVMLIB"];
if (flags & SG_NORELOC)
[setFlags addObject:@"NORELOC"];
if (flags & SG_PROTECTED_VERSION_1)
[setFlags addObject:@"PROTECTED_VERSION_1"];
if ([setFlags count] == 0)
return @"(none)";
return [setFlags componentsJoinedByString:@" "];
}
- (NSString *)extraDescription;
{
return [NSString stringWithFormat:@"name: '%@', vmaddr: 0x%08x - 0x%08x [0x%08x], offset: %d, flags: 0x%x (%@), nsects: %d, sections: %@",
name, segmentCommand.vmaddr, segmentCommand.vmaddr + segmentCommand.vmsize - 1, segmentCommand.vmsize, segmentCommand.fileoff,
[self flags], [self flagDescription], segmentCommand.nsects, sections];
}
// TODO (2003-12-06): Might want to make this a range.
- (BOOL)containsAddress:(unsigned long)vmaddr;
{
return (vmaddr >= segmentCommand.vmaddr) && (vmaddr < segmentCommand.vmaddr + segmentCommand.vmsize);
}
- (CDSection *)sectionContainingVMAddr:(unsigned long)vmaddr;
{
int count, index;
count = [sections count];
for (index = 0; index < count; index++) {
CDSection *aSection;
aSection = [sections objectAtIndex:index];
if ([aSection containsAddress:vmaddr] == YES)
return aSection;
}
return nil;
}
- (unsigned long)segmentOffsetForVMAddr:(unsigned long)vmaddr;
{
CDSection *section;
section = [self sectionContainingVMAddr:vmaddr];
NSLog(@"section: %@", section);
return [section segmentOffsetForVMAddr:vmaddr];
}
- (CDSection *)sectionWithName:(NSString *)aName;
{
int count, index;
count = [sections count];
for (index = 0; index < count; index++) {
CDSection *aSection;
aSection = [sections objectAtIndex:index];
if ([[aSection sectionName] isEqual:aName] == YES)
return aSection;
}
return nil;
}
- (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose;
{
[super appendToString:resultString verbose:isVerbose];
[resultString appendFormat:@" segname %@\n", [self name]];
[resultString appendFormat:@" vmaddr 0x%08x\n", segmentCommand.vmaddr];
[resultString appendFormat:@" vmsize 0x%08x\n", segmentCommand.vmsize];
[resultString appendFormat:@" fileoff %d\n", segmentCommand.fileoff];
[resultString appendFormat:@" filesize %d\n", segmentCommand.filesize];
[resultString appendFormat:@" maxprot 0x%08x\n", segmentCommand.maxprot];
[resultString appendFormat:@" initprot 0x%08x\n", segmentCommand.initprot];
[resultString appendFormat:@" nsects %d\n", segmentCommand.nsects];
if (isVerbose)
[resultString appendFormat:@" flags %@\n", [self flagDescription]];
else
[resultString appendFormat:@" flags 0x%x\n", segmentCommand.flags];
}
@end