blob: 63ba400d3bb207177387934fa06658ff010330dd [file] [log] [blame]
// -*- 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-2011 Steve Nygard.
#import "CDLCSymbolTable.h"
#include <mach-o/nlist.h>
#import "CDMachOFile.h"
#import "CDSymbol.h"
#import "CDLCSegment.h"
@implementation CDLCSymbolTable
- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
{
if ((self = [super initWithDataCursor:cursor])) {
symtabCommand.cmd = [cursor readInt32];
symtabCommand.cmdsize = [cursor readInt32];
symtabCommand.symoff = [cursor readInt32];
symtabCommand.nsyms = [cursor readInt32];
symtabCommand.stroff = [cursor readInt32];
symtabCommand.strsize = [cursor readInt32];
// symoff is at the start of the first section (__pointers) of the __IMPORT segment
// stroff falls within the __LINKEDIT segment
#if 0
NSLog(@"symtab: %08x %08x %08x %08x %08x %08x",
symtabCommand.cmd, symtabCommand.cmdsize,
symtabCommand.symoff, symtabCommand.nsyms, symtabCommand.stroff, symtabCommand.strsize);
NSLog(@"data offset for stroff: %lu", [aMachOFile dataOffsetForAddress:symtabCommand.stroff]);
#endif
symbols = nil;
baseAddress = 0;
classSymbols = nil;
flags.didFindBaseAddress = NO;
flags.didWarnAboutUnfoundBaseAddress = NO;
}
return self;
}
- (void)dealloc;
{
[symbols release];
[classSymbols release];
[super dealloc];
}
#pragma mark - Debugging
- (NSString *)extraDescription;
{
return [NSString stringWithFormat:@"symoff: 0x%08x (%u), nsyms: 0x%08x (%u), stroff: 0x%08x (%u), strsize: 0x%08x (%u)",
symtabCommand.symoff, symtabCommand.symoff, symtabCommand.nsyms, symtabCommand.nsyms,
symtabCommand.stroff, symtabCommand.stroff, symtabCommand.strsize, symtabCommand.strsize];
}
#pragma mark -
- (uint32_t)cmd;
{
return symtabCommand.cmd;
}
- (uint32_t)cmdsize;
{
return symtabCommand.cmdsize;
}
#define CD_VM_PROT_RW (VM_PROT_READ|VM_PROT_WRITE)
- (void)loadSymbols;
{
for (CDLoadCommand *loadCommand in [nonretained_machOFile loadCommands]) {
if ([loadCommand isKindOfClass:[CDLCSegment class]]) {
CDLCSegment *segment = (CDLCSegment *)loadCommand;
if (([segment initprot] & CD_VM_PROT_RW) == CD_VM_PROT_RW) {
//NSLog(@"segment... initprot = %08x, addr= %016lx *** r/w", [segment initprot], [segment vmaddr]);
baseAddress = [segment vmaddr];
flags.didFindBaseAddress = YES;
break;
}
}
}
NSMutableArray *_symbols = [[NSMutableArray alloc] init];
NSMutableDictionary *_classSymbols = [[NSMutableDictionary alloc] init];
CDMachOFileDataCursor *cursor = [[CDMachOFileDataCursor alloc] initWithFile:nonretained_machOFile offset:symtabCommand.symoff];
//NSLog(@"offset= %lu", [cursor offset]);
//NSLog(@"stroff= %lu", symtabCommand.stroff);
//NSLog(@"strsize= %lu", symtabCommand.strsize);
const char *strtab = [[nonretained_machOFile machOData] bytes] + symtabCommand.stroff;
if (![nonretained_machOFile uses64BitABI]) {
//NSLog(@"32 bit...");
//NSLog(@" str table index type sect desc value");
//NSLog(@" --------------- ---- ---- ---- --------");
for (uint32_t index = 0; index < symtabCommand.nsyms; index++) {
struct nlist nlist;
nlist.n_un.n_strx = [cursor readInt32];
nlist.n_type = [cursor readByte];
nlist.n_sect = [cursor readByte];
nlist.n_desc = [cursor readInt16];
nlist.n_value = [cursor readInt32];
#if 0
NSLog(@"%5u: %08x %02x %02x %04x %08x - %s",
index, nlist.n_un.n_strx, nlist.n_type, nlist.n_sect, nlist.n_desc, nlist.n_value, strtab + nlist.n_un.n_strx);
#endif
const char *ptr = strtab + nlist.n_un.n_strx;
NSString *str = [[NSString alloc] initWithBytes:ptr length:strlen(ptr) encoding:NSASCIIStringEncoding];
CDSymbol *symbol = [[CDSymbol alloc] initWithName:str machOFile:nonretained_machOFile nlist32:nlist];
[_symbols addObject:symbol];
[symbol release];
[str release];
}
//NSLog(@"Loaded %lu 32-bit symbols", [symbols count]);
} else {
//NSLog(@" str table index type sect desc value");
//NSLog(@" --------------- ---- ---- ---- ----------------");
for (uint32_t index = 0; index < symtabCommand.nsyms; index++) {
struct nlist_64 nlist;
nlist.n_un.n_strx = [cursor readInt32];
nlist.n_type = [cursor readByte];
nlist.n_sect = [cursor readByte];
nlist.n_desc = [cursor readInt16];
nlist.n_value = [cursor readInt64];
#if 0
NSLog(@"%5u: %08x %02x %02x %04x %016x - %s",
index, nlist.n_un.n_strx, nlist.n_type, nlist.n_sect, nlist.n_desc, nlist.n_value, strtab + nlist.n_un.n_strx);
#endif
const char *ptr = strtab + nlist.n_un.n_strx;
NSString *str = [[NSString alloc] initWithBytes:ptr length:strlen(ptr) encoding:NSASCIIStringEncoding];
CDSymbol *symbol = [[CDSymbol alloc] initWithName:str machOFile:nonretained_machOFile nlist64:nlist];
[_symbols addObject:symbol];
if ([str hasPrefix:ObjCClassSymbolPrefix] && [symbol value] != 0) {
NSString *className = [str substringFromIndex:[ObjCClassSymbolPrefix length]];
[_classSymbols setObject:symbol forKey:className];
}
[symbol release];
[str release];
}
//NSLog(@"Loaded %lu 64-bit symbols", [symbols count]);
}
[cursor release];
symbols = [_symbols copy]; [_symbols release];
classSymbols = [_classSymbols copy]; [_classSymbols release];
//NSLog(@"symbols: %@", symbols);
}
- (uint32_t)symoff;
{
return symtabCommand.symoff;
}
- (uint32_t)nsyms;
{
return symtabCommand.nsyms;
}
- (uint32_t)stroff;
{
return symtabCommand.stroff;
}
- (uint32_t)strsize;
{
return symtabCommand.strsize;
}
- (NSUInteger)baseAddress;
{
if (flags.didFindBaseAddress == NO && flags.didWarnAboutUnfoundBaseAddress == NO) {
fprintf(stderr, "Warning: Couldn't find first read/write segment for base address of relocation entries.\n");
flags.didWarnAboutUnfoundBaseAddress = YES;
}
return baseAddress;
}
- (NSArray *)symbols;
{
return symbols;
}
- (CDSymbol *)symbolForClass:(NSString *)className;
{
return [classSymbols objectForKey:className];
}
@end