Index: class-dump/src/CDLCDyldInfo.m |
=================================================================== |
--- class-dump/src/CDLCDyldInfo.m (revision 0) |
+++ class-dump/src/CDLCDyldInfo.m (revision 0) |
@@ -0,0 +1,662 @@ |
+// -*- 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 "CDLCDyldInfo.h" |
+ |
+#import "CDDataCursor.h" |
+#import "CDMachOFile.h" |
+ |
+#import "CDLCSegment.h" |
+ |
+static BOOL debugBindOps = NO; |
+static BOOL debugExportedSymbols = NO; |
+ |
+// Can use dyldinfo(1) to view info. |
+ |
+// http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-assembler/uleb128.html |
+// uleb128 stands for "unsigned little endian base 128." |
+// This is a compact, variable length representation of numbers used by the DWARF symbolic debugging format. |
+ |
+// Top bit of byte is set until last byte. |
+// Other 7 bits are the "slice". |
+// Basically, it represents the low order bits 7 at a time, and can stop when the rest of the bits would be zero. |
+// This needs to modify ptr. |
+ |
+// For example, uleb with these bytes: e8 d7 15 |
+// 0xe8 = 1110 1000 |
+// 0xd7 = 1101 0111 |
+// 0x15 = 0001 0101 |
+ |
+// .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... .... |
+// 0xe8 1 1101000 .... .... .... .... .... .... .... .... .... .... .... .... .... .... .110 1000 |
+// 0xd7 1 1010111 .... .... .... .... .... .... .... .... .... .... .... .... ..10 1011 1110 1000 |
+// 0x15 0 0010101 .... .... .... .... .... .... .... .... .... .... .... .... ..10 1011 1110 1000 |
+// 0x15 0 0010101 .... .... .... .... .... .... .... .... .... .... ...0 0101 0110 1011 1110 1000 |
+// Result is: 0x056be8 |
+// So... 24 bits to encode 64 bits |
+ |
+static uint64_t read_uleb128(const uint8_t **ptrptr, const uint8_t *end) |
+{ |
+ static uint32_t maxlen = 0; |
+ const uint8_t *ptr = *ptrptr; |
+ uint64_t result = 0; |
+ int bit = 0; |
+ |
+ //NSLog(@"read_uleb128()"); |
+ do { |
+ uint64_t slice; |
+ |
+ if (ptr == end) { |
+ NSLog(@"Malformed uleb128"); |
+ exit(88); |
+ } |
+ |
+ //NSLog(@"byte: %02x", *ptr); |
+ slice = *ptr & 0x7f; |
+ |
+ if (bit >= 64 || slice << bit >> bit != slice) { |
+ NSLog(@"uleb128 too big"); |
+ exit(88); |
+ } else { |
+ result |= (slice << bit); |
+ bit += 7; |
+ } |
+ } |
+ while ((*ptr++ & 0x80) != 0); |
+ |
+ if (maxlen < ptr - *ptrptr) { |
+ NSMutableArray *byteStrs; |
+ const uint8_t *ptr2 = *ptrptr; |
+ |
+ byteStrs = [NSMutableArray array]; |
+ do { |
+ [byteStrs addObject:[NSString stringWithFormat:@"%02x", *ptr2]]; |
+ } while (++ptr2 < ptr); |
+ //NSLog(@"max uleb length now: %u (%@)", ptr - *ptrptr, [byteStrs componentsJoinedByString:@" "]); |
+ //NSLog(@"sizeof(uint64_t): %u, sizeof(uintptr_t): %u", sizeof(uint64_t), sizeof(uintptr_t)); |
+ maxlen = ptr - *ptrptr; |
+ } |
+ |
+ *ptrptr = ptr; |
+ return result; |
+} |
+ |
+static int64_t read_sleb128(const uint8_t **ptrptr, const uint8_t *end) |
+{ |
+ const uint8_t *ptr = *ptrptr; |
+ |
+ int64_t result = 0; |
+ int bit = 0; |
+ uint8_t byte; |
+ |
+ //NSLog(@"read_sleb128()"); |
+ do { |
+ if (ptr == end) { |
+ NSLog(@"Malformed sleb128"); |
+ exit(88); |
+ } |
+ |
+ byte = *ptr++; |
+ //NSLog(@"%02x", byte); |
+ result |= ((byte & 0x7f) << bit); |
+ bit += 7; |
+ } while ((byte & 0x80) != 0); |
+ |
+ //NSLog(@"result before sign extend: %ld", result); |
+ // sign extend negative numbers |
+ // This essentially clears out from -1 the low order bits we've already set, and combines that with our bits. |
+ if ( (byte & 0x40) != 0 ) |
+ result |= (-1LL) << bit; |
+ |
+ //NSLog(@"result after sign extend: %ld", result); |
+ |
+ //NSLog(@"ptr before: %p, after: %p", *ptrptr, ptr); |
+ *ptrptr = ptr; |
+ return result; |
+} |
+ |
+static NSString *CDRebaseTypeString(uint8_t type) |
+{ |
+ switch (type) { |
+ case REBASE_TYPE_POINTER: return @"Pointer"; |
+ case REBASE_TYPE_TEXT_ABSOLUTE32: return @"Absolute 32"; |
+ case REBASE_TYPE_TEXT_PCREL32: return @"PC rel 32"; |
+ } |
+ |
+ return @"Unknown"; |
+} |
+ |
+static NSString *CDBindTypeString(uint8_t type) |
+{ |
+ switch (type) { |
+ case REBASE_TYPE_POINTER: return @"Pointer"; |
+ case REBASE_TYPE_TEXT_ABSOLUTE32: return @"Absolute 32"; |
+ case REBASE_TYPE_TEXT_PCREL32: return @"PC rel 32"; |
+ } |
+ |
+ return @"Unknown"; |
+} |
+ |
+// Need acces to: list of segments |
+ |
+@implementation CDLCDyldInfo |
+ |
+- (id)initWithDataCursor:(CDDataCursor *)cursor machOFile:(CDMachOFile *)aMachOFile; |
+{ |
+ if ([super initWithDataCursor:cursor machOFile:aMachOFile] == nil) |
+ return nil; |
+ |
+ dyldInfoCommand.cmd = [cursor readInt32]; |
+ dyldInfoCommand.cmdsize = [cursor readInt32]; |
+ |
+ dyldInfoCommand.rebase_off = [cursor readInt32]; |
+ dyldInfoCommand.rebase_size = [cursor readInt32]; |
+ dyldInfoCommand.bind_off = [cursor readInt32]; |
+ dyldInfoCommand.bind_size = [cursor readInt32]; |
+ dyldInfoCommand.weak_bind_off = [cursor readInt32]; |
+ dyldInfoCommand.weak_bind_size = [cursor readInt32]; |
+ dyldInfoCommand.lazy_bind_off = [cursor readInt32]; |
+ dyldInfoCommand.lazy_bind_size = [cursor readInt32]; |
+ dyldInfoCommand.export_off = [cursor readInt32]; |
+ dyldInfoCommand.export_size = [cursor readInt32]; |
+ |
+#if 0 |
+ NSLog(@" cmdsize: %08x", dyldInfoCommand.cmdsize); |
+ NSLog(@" rebase_off: %08x", dyldInfoCommand.rebase_off); |
+ NSLog(@" rebase_size: %08x", dyldInfoCommand.rebase_size); |
+ NSLog(@" bind_off: %08x", dyldInfoCommand.bind_off); |
+ NSLog(@" bind_size: %08x", dyldInfoCommand.bind_size); |
+ NSLog(@" weak_bind_off: %08x", dyldInfoCommand.weak_bind_off); |
+ NSLog(@"weak_bind_size: %08x", dyldInfoCommand.weak_bind_size); |
+ NSLog(@" lazy_bind_off: %08x", dyldInfoCommand.lazy_bind_off); |
+ NSLog(@"lazy_bind_size: %08x", dyldInfoCommand.lazy_bind_size); |
+ NSLog(@" export_off: %08x", dyldInfoCommand.export_off); |
+ NSLog(@" export_size: %08x", dyldInfoCommand.export_size); |
+#endif |
+ |
+ if ([aMachOFile uses64BitABI]) |
+ ptrSize = sizeof(uint64_t); |
+ else |
+ ptrSize = sizeof(uint32_t); |
+ |
+ symbolNamesByAddress = [[NSMutableDictionary alloc] init]; |
+ |
+ //[self logRebaseInfo]; |
+ [self logBindInfo]; // Acutally loads it for now. |
+ [self logWeakBindInfo]; |
+ //[self logLazyBindInfo]; |
+ //[self logExportedSymbols]; |
+ |
+ //NSLog(@"symbolNamesByAddress: %@", symbolNamesByAddress); |
+ |
+ return self; |
+} |
+ |
+- (void)dealloc; |
+{ |
+ [symbolNamesByAddress release]; |
+ |
+ [super dealloc]; |
+} |
+ |
+- (uint32_t)cmd; |
+{ |
+ return dyldInfoCommand.cmd; |
+} |
+ |
+- (uint32_t)cmdsize; |
+{ |
+ return dyldInfoCommand.cmdsize; |
+} |
+ |
+- (NSString *)symbolNameForAddress:(NSUInteger)address; |
+{ |
+ return [symbolNamesByAddress objectForKey:[NSNumber numberWithUnsignedInteger:address]]; |
+} |
+ |
+// |
+// Rebasing |
+// |
+ |
+// address, slide, type |
+// slide is constant throughout the loop |
+- (void)logRebaseInfo; |
+{ |
+ const uint8_t *start, *end, *ptr; |
+ BOOL isDone = NO; |
+ NSArray *segments; |
+ uint64_t address; |
+ uint8_t type; |
+ NSUInteger rebaseCount = 0; |
+ |
+ segments = [nonretained_machOFile segments]; |
+ NSLog(@"segments: %@", segments); |
+ NSParameterAssert([segments count] > 0); |
+ |
+ address = [[segments objectAtIndex:0] vmaddr]; |
+ type = 0; |
+ |
+ NSLog(@"----------------------------------------------------------------------"); |
+ NSLog(@"rebase_off: %u, rebase_size: %u", dyldInfoCommand.rebase_off, dyldInfoCommand.rebase_size); |
+ start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.rebase_off; |
+ end = start + dyldInfoCommand.rebase_size; |
+ |
+ NSLog(@"address: %016lx", address); |
+ ptr = start; |
+ while ((ptr < end) && isDone == NO) { |
+ uint8_t immediate, opcode; |
+ |
+ immediate = *ptr & REBASE_IMMEDIATE_MASK; |
+ opcode = *ptr & REBASE_OPCODE_MASK; |
+ ptr++; |
+ |
+ switch (opcode) { |
+ case REBASE_OPCODE_DONE: |
+ //NSLog(@"REBASE_OPCODE: DONE"); |
+ isDone = YES; |
+ break; |
+ |
+ case REBASE_OPCODE_SET_TYPE_IMM: |
+ //NSLog(@"REBASE_OPCODE: SET_TYPE_IMM, type = 0x%x // %@", immediate, CDRebaseTypeString(immediate)); |
+ type = immediate; |
+ break; |
+ |
+ case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: { |
+ uint64_t val = read_uleb128(&ptr, end); |
+ |
+ //NSLog(@"REBASE_OPCODE: SET_SEGMENT_AND_OFFSET_ULEB, segment index: %u, offset: %016lx", immediate, val); |
+ NSParameterAssert(immediate < [segments count]); |
+ address = [[segments objectAtIndex:immediate] vmaddr] + val; |
+ //NSLog(@" address: %016lx", address); |
+ break; |
+ } |
+ |
+ case REBASE_OPCODE_ADD_ADDR_ULEB: { |
+ uint64_t val = read_uleb128(&ptr, end); |
+ |
+ //NSLog(@"REBASE_OPCODE: ADD_ADDR_ULEB, addr += %016lx", val); |
+ address += val; |
+ //NSLog(@" address: %016lx", address); |
+ break; |
+ } |
+ |
+ case REBASE_OPCODE_ADD_ADDR_IMM_SCALED: |
+ // I expect sizeof(uintptr_t) == sizeof(uint64_t) |
+ //NSLog(@"REBASE_OPCODE: ADD_ADDR_IMM_SCALED, addr += %u * %u", immediate, sizeof(uint64_t)); |
+ address += immediate * ptrSize; |
+ //NSLog(@" address: %016lx", address); |
+ break; |
+ |
+ case REBASE_OPCODE_DO_REBASE_IMM_TIMES: { |
+ uint32_t index; |
+ |
+ //NSLog(@"REBASE_OPCODE: DO_REBASE_IMM_TIMES, count: %u", immediate); |
+ for (index = 0; index < immediate; index++) { |
+ [self rebaseAddress:address type:type]; |
+ address += ptrSize; |
+ } |
+ rebaseCount += immediate; |
+ break; |
+ } |
+ |
+ case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: { |
+ uint64_t count, index; |
+ |
+ count = read_uleb128(&ptr, end); |
+ |
+ //NSLog(@"REBASE_OPCODE: DO_REBASE_ULEB_TIMES, count: 0x%016lx", count); |
+ for (index = 0; index < count; index++) { |
+ [self rebaseAddress:address type:type]; |
+ address += ptrSize; |
+ } |
+ rebaseCount += count; |
+ break; |
+ } |
+ |
+ case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: { |
+ uint64_t val; |
+ |
+ val = read_uleb128(&ptr, end); |
+ // --------------------------------------------------------: |
+ //NSLog(@"REBASE_OPCODE: DO_REBASE_ADD_ADDR_ULEB, addr += 0x%016lx", val); |
+ [self rebaseAddress:address type:type]; |
+ address += ptrSize + val; |
+ rebaseCount++; |
+ break; |
+ } |
+ |
+ case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: { |
+ uint64_t count, skip, index; |
+ |
+ count = read_uleb128(&ptr, end); |
+ skip = read_uleb128(&ptr, end); |
+ //NSLog(@"REBASE_OPCODE: DO_REBASE_ULEB_TIMES_SKIPPING_ULEB, count: %016lx, skip: %016lx", count, skip); |
+ for (index = 0; index < count; index++) { |
+ [self rebaseAddress:address type:type]; |
+ address += ptrSize + skip; |
+ } |
+ rebaseCount += count; |
+ break; |
+ } |
+ |
+ default: |
+ NSLog(@"Unknown opcode op: %x, imm: %x", opcode, immediate); |
+ exit(99); |
+ } |
+ } |
+ |
+ NSLog(@" ptr: %p, end: %p, bytes left over: %u", ptr, end, end - ptr); |
+ NSLog(@" rebaseCount: %lu", rebaseCount); |
+ NSLog(@"----------------------------------------------------------------------"); |
+} |
+ |
+- (void)rebaseAddress:(uint64_t)address type:(uint8_t)type; |
+{ |
+ //NSLog(@" Rebase 0x%016lx, type: %x (%@)", address, type, CDRebaseTypeString(type)); |
+} |
+ |
+// |
+// Binding |
+// |
+ |
+// From mach-o/loader.h: |
+// Dyld binds an image during the loading process, if the image requires any pointers to be initialized to symbols in other images. |
+// Conceptually the bind information is a table of tuples: |
+// <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend> |
+ |
+- (void)logBindInfo; |
+{ |
+ const uint8_t *start, *end; |
+ |
+ if (debugBindOps) { |
+ NSLog(@"----------------------------------------------------------------------"); |
+ NSLog(@"bind_off: %u, bind_size: %u", dyldInfoCommand.bind_off, dyldInfoCommand.bind_size); |
+ } |
+ start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.bind_off; |
+ end = start + dyldInfoCommand.bind_size; |
+ |
+ [self logBindOps:start end:end isLazy:NO]; |
+} |
+ |
+- (void)logWeakBindInfo; |
+{ |
+ const uint8_t *start, *end; |
+ |
+ if (debugBindOps) { |
+ NSLog(@"----------------------------------------------------------------------"); |
+ NSLog(@"weak_bind_off: %u, weak_bind_size: %u", dyldInfoCommand.weak_bind_off, dyldInfoCommand.weak_bind_size); |
+ } |
+ start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.weak_bind_off; |
+ end = start + dyldInfoCommand.weak_bind_size; |
+ |
+ [self logBindOps:start end:end isLazy:NO]; |
+} |
+ |
+- (void)logLazyBindInfo; |
+{ |
+ const uint8_t *start, *end; |
+ |
+ if (debugBindOps) { |
+ NSLog(@"----------------------------------------------------------------------"); |
+ NSLog(@"lazy_bind_off: %u, lazy_bind_size: %u", dyldInfoCommand.lazy_bind_off, dyldInfoCommand.lazy_bind_size); |
+ } |
+ start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.lazy_bind_off; |
+ end = start + dyldInfoCommand.lazy_bind_size; |
+ |
+ [self logBindOps:start end:end isLazy:YES]; |
+} |
+ |
+- (void)logBindOps:(const uint8_t *)start end:(const uint8_t *)end isLazy:(BOOL)isLazy; |
+{ |
+ BOOL isDone = NO; |
+ NSUInteger bindCount = 0; |
+ |
+ const uint8_t *ptr; |
+ NSArray *segments; |
+ uint64_t address; |
+ int64_t libraryOrdinal = 0; |
+ uint8_t type = 0; |
+ int64_t addend = 0; |
+ uint8_t segmentIndex = 0; |
+ const char *symbolName = NULL; |
+ uint8_t symbolFlags = 0; |
+ |
+ segments = [nonretained_machOFile segments]; |
+ //NSLog(@"segments: %@", segments); |
+ NSParameterAssert([segments count] > 0); |
+ |
+ address = [[segments objectAtIndex:0] vmaddr]; |
+ |
+ ptr = start; |
+ while ((ptr < end) && isDone == NO) { |
+ uint8_t immediate, opcode; |
+ |
+ immediate = *ptr & BIND_IMMEDIATE_MASK; |
+ opcode = *ptr & BIND_OPCODE_MASK; |
+ ptr++; |
+ |
+ switch (opcode) { |
+ case BIND_OPCODE_DONE: |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: DONE"); |
+ |
+ // The lazy bindings have one of these at the end of each bind. |
+ if (isLazy == NO) |
+ isDone = YES; |
+ break; |
+ |
+ case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: |
+ libraryOrdinal = immediate; |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_DYLIB_ORDINAL_IMM, libraryOrdinal = %ld", libraryOrdinal); |
+ break; |
+ |
+ case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: |
+ libraryOrdinal = read_uleb128(&ptr, end); |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_DYLIB_ORDINAL_ULEB, libraryOrdinal = %ld", libraryOrdinal); |
+ break; |
+ |
+ case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: { |
+ // Special means negative |
+ if (immediate == 0) |
+ libraryOrdinal = 0; |
+ else { |
+ int8_t val = immediate | BIND_OPCODE_MASK; // This sign extends the value |
+ |
+ libraryOrdinal = val; |
+ } |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_DYLIB_SPECIAL_IMM, libraryOrdinal = %ld", libraryOrdinal); |
+ break; |
+ } |
+ |
+ case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: |
+ symbolName = (const char *)ptr; |
+ symbolFlags = immediate; |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_SYMBOL_TRAILING_FLAGS_IMM, flags: %02x, str = %s", symbolFlags, symbolName); |
+ while (*ptr != 0) |
+ ptr++; |
+ |
+ ptr++; // skip the trailing zero |
+ |
+ break; |
+ |
+ case BIND_OPCODE_SET_TYPE_IMM: |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_TYPE_IMM, type = %u (%@)", immediate, CDBindTypeString(immediate)); |
+ type = immediate; |
+ break; |
+ |
+ case BIND_OPCODE_SET_ADDEND_SLEB: |
+ addend = read_sleb128(&ptr, end); |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_ADDEND_SLEB, addend = %ld", addend); |
+ break; |
+ |
+ case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: { |
+ uint64_t val; |
+ |
+ segmentIndex = immediate; |
+ val = read_uleb128(&ptr, end); |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: SET_SEGMENT_AND_OFFSET_ULEB, segmentIndex: %u, offset: 0x%016lx", segmentIndex, val); |
+ address = [[segments objectAtIndex:segmentIndex] vmaddr] + val; |
+ if (debugBindOps) NSLog(@" address = 0x%016lx", address); |
+ break; |
+ } |
+ |
+ case BIND_OPCODE_ADD_ADDR_ULEB: { |
+ uint64_t val; |
+ |
+ val = read_uleb128(&ptr, end); |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: ADD_ADDR_ULEB, addr += 0x%016lx", val); |
+ address += val; |
+ break; |
+ } |
+ |
+ case BIND_OPCODE_DO_BIND: |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND"); |
+ [self bindAddress:address type:type symbolName:symbolName flags:symbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
+ address += ptrSize; |
+ bindCount++; |
+ break; |
+ |
+ case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: { |
+ uint64_t val; |
+ |
+ val = read_uleb128(&ptr, end); |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND_ADD_ADDR_ULEB, address += %016lx", val); |
+ [self bindAddress:address type:type symbolName:symbolName flags:symbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
+ address += ptrSize + val; |
+ bindCount++; |
+ break; |
+ } |
+ |
+ case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND_ADD_ADDR_IMM_SCALED, address += %u * %u", immediate, ptrSize); |
+ [self bindAddress:address type:type symbolName:symbolName flags:symbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
+ address += ptrSize + immediate * ptrSize; |
+ bindCount++; |
+ break; |
+ |
+ case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: { |
+ uint64_t count, skip, index; |
+ |
+ count = read_uleb128(&ptr, end); |
+ skip = read_uleb128(&ptr, end); |
+ if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND_ULEB_TIMES_SKIPPING_ULEB, count: %016lx, skip: %016lx", count, skip); |
+ for (index = 0; index < count; index++) { |
+ [self bindAddress:address type:type symbolName:symbolName flags:symbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
+ address += ptrSize + skip; |
+ } |
+ bindCount += count; |
+ break; |
+ } |
+ |
+ default: |
+ NSLog(@"Unknown opcode op: %x, imm: %x", opcode, immediate); |
+ exit(99); |
+ } |
+ } |
+ |
+ if (debugBindOps) { |
+ NSLog(@" ptr: %p, end: %p, bytes left over: %u", ptr, end, end - ptr); |
+ NSLog(@" bindCount: %lu", bindCount); |
+ NSLog(@"----------------------------------------------------------------------"); |
+ } |
+} |
+ |
+- (void)bindAddress:(uint64_t)address type:(uint8_t)type symbolName:(const char *)symbolName flags:(uint8_t)flags |
+ addend:(int64_t)addend libraryOrdinal:(int64_t)libraryOrdinal; |
+{ |
+ NSNumber *key; |
+ NSString *str; |
+ |
+#if 0 |
+ NSLog(@" Bind address: %016lx, type: 0x%02x, flags: %02x, addend: %016lx, libraryOrdinal: %ld, symbolName: %s", |
+ address, type, flags, addend, libraryOrdinal, symbolName); |
+#endif |
+ |
+ key = [NSNumber numberWithUnsignedInteger:address]; // I don't think 32-bit will dump 64-bit stuff. |
+ str = [[NSString alloc] initWithUTF8String:symbolName]; |
+ [symbolNamesByAddress setObject:str forKey:key]; |
+ [str release]; |
+} |
+ |
+// |
+// Exported symbols |
+// |
+ |
+- (void)logExportedSymbols; |
+{ |
+ const uint8_t *start, *end; |
+ |
+ if (debugExportedSymbols) { |
+ NSLog(@"----------------------------------------------------------------------"); |
+ NSLog(@"export_off: %u, export_size: %u", dyldInfoCommand.export_off, dyldInfoCommand.export_size); |
+ NSLog(@"hexdump -Cv -s %u -n %u", dyldInfoCommand.export_off, dyldInfoCommand.export_size); |
+ } |
+ |
+ start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.export_off; |
+ end = start + dyldInfoCommand.export_size; |
+ |
+ NSLog(@" Type Flags Offset Name"); |
+ NSLog(@"------------- ----- ---------------- ----"); |
+ [self printSymbols:start end:end prefix:@"" offset:0]; |
+} |
+ |
+- (void)printSymbols:(const uint8_t *)start end:(const uint8_t *)end prefix:(NSString *)prefix offset:(uint32_t)offset; |
+{ |
+ uint8_t terminalSize; |
+ const uint8_t *ptr, *tptr; |
+ uint8_t childCount, index; |
+ |
+ //NSLog(@" > %s, %p-%p, offset: %lx = %p", _cmd, start, end, offset, start + offset); |
+ |
+ ptr = start + offset; |
+ NSParameterAssert(ptr < end); |
+ |
+ terminalSize = *ptr++; |
+ tptr = ptr; |
+ //NSLog(@"terminalSize: %u", terminalSize); |
+ |
+ ptr += terminalSize; |
+ |
+ childCount = *ptr++; |
+ |
+ if (terminalSize > 0) { |
+ uint64_t flags; |
+ uint8_t kind; |
+ |
+ //NSLog(@"symbol: '%@', terminalSize: %u", prefix, terminalSize); |
+ flags = read_uleb128(&tptr, end); |
+ kind = flags & EXPORT_SYMBOL_FLAGS_KIND_MASK; |
+ if (kind == EXPORT_SYMBOL_FLAGS_KIND_REGULAR) { |
+ uint64_t offset; |
+ |
+ offset = read_uleb128(&tptr, end); |
+ NSLog(@" Regular: %04x %016lx %@", flags, offset, prefix); |
+ //NSLog(@" Regular: %04x 0x%08x %@", flags, offset, prefix); |
+ } else if (kind == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL) { |
+ NSLog(@"Thread Local: %04x %@, terminalSize: %u", flags, prefix, terminalSize); |
+ } else { |
+ NSLog(@" Unknown: %04x %x, name: %@, terminalSize: %u", flags, kind, prefix, terminalSize); |
+ } |
+ } |
+ |
+ for (index = 0; index < childCount; index++) { |
+ const uint8_t *edgeStart = ptr; |
+ uint32_t length; |
+ uint64_t nodeOffset; |
+ |
+ while (*ptr++ != 0) |
+ ; |
+ |
+ length = ptr - edgeStart; |
+ //NSLog(@"edge length: %u, edge: '%s'", length, edgeStart); |
+ nodeOffset = read_uleb128(&ptr, end); |
+ //NSLog(@"node offset: %lx", nodeOffset); |
+ |
+ [self printSymbols:start end:end prefix:[NSString stringWithFormat:@"%@%s", prefix, edgeStart] offset:nodeOffset]; |
+ } |
+ |
+ //NSLog(@"< %s, %p-%p, offset: %lx = %p", _cmd, start, end, offset, start + offset); |
+} |
+ |
+@end |
Property changes on: class-dump/src/CDLCDyldInfo.m |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |