OLD | NEW |
(Empty) | |
| 1 // -*- mode: ObjC -*- |
| 2 |
| 3 // This file is part of class-dump, a utility for examining the Objective-C seg
ment of Mach-O files. |
| 4 // Copyright (C) 1997-1998, 2000-2001, 2004-2010 Steve Nygard. |
| 5 |
| 6 #import "CDLCDyldInfo.h" |
| 7 |
| 8 #import "CDDataCursor.h" |
| 9 #import "CDMachOFile.h" |
| 10 |
| 11 #import "CDLCSegment.h" |
| 12 |
| 13 static BOOL debugBindOps = NO; |
| 14 static BOOL debugExportedSymbols = NO; |
| 15 |
| 16 // Can use dyldinfo(1) to view info. |
| 17 |
| 18 // http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gnu-assembler/ule
b128.html |
| 19 // uleb128 stands for "unsigned little endian base 128." |
| 20 // This is a compact, variable length representation of numbers used by the DWAR
F symbolic debugging format. |
| 21 |
| 22 // Top bit of byte is set until last byte. |
| 23 // Other 7 bits are the "slice". |
| 24 // Basically, it represents the low order bits 7 at a time, and can stop when th
e rest of the bits would be zero. |
| 25 // This needs to modify ptr. |
| 26 |
| 27 // For example, uleb with these bytes: e8 d7 15 |
| 28 // 0xe8 = 1110 1000 |
| 29 // 0xd7 = 1101 0111 |
| 30 // 0x15 = 0001 0101 |
| 31 |
| 32 // .... .... .... .... .... .... .... .... .... .... .... .... .
... .... .... .... |
| 33 // 0xe8 1 1101000 .... .... .... .... .... .... .... .... .... .... .... .... .
... .... .110 1000 |
| 34 // 0xd7 1 1010111 .... .... .... .... .... .... .... .... .... .... .... .... .
.10 1011 1110 1000 |
| 35 // 0x15 0 0010101 .... .... .... .... .... .... .... .... .... .... .... .... .
.10 1011 1110 1000 |
| 36 // 0x15 0 0010101 .... .... .... .... .... .... .... .... .... .... ...0 0101 0
110 1011 1110 1000 |
| 37 // Result is: 0x056be8 |
| 38 // So... 24 bits to encode 64 bits |
| 39 |
| 40 static uint64_t read_uleb128(const uint8_t **ptrptr, const uint8_t *end) |
| 41 { |
| 42 static uint32_t maxlen = 0; |
| 43 const uint8_t *ptr = *ptrptr; |
| 44 uint64_t result = 0; |
| 45 int bit = 0; |
| 46 |
| 47 //NSLog(@"read_uleb128()"); |
| 48 do { |
| 49 uint64_t slice; |
| 50 |
| 51 if (ptr == end) { |
| 52 NSLog(@"Malformed uleb128"); |
| 53 exit(88); |
| 54 } |
| 55 |
| 56 //NSLog(@"byte: %02x", *ptr); |
| 57 slice = *ptr & 0x7f; |
| 58 |
| 59 if (bit >= 64 || slice << bit >> bit != slice) { |
| 60 NSLog(@"uleb128 too big"); |
| 61 exit(88); |
| 62 } else { |
| 63 result |= (slice << bit); |
| 64 bit += 7; |
| 65 } |
| 66 } |
| 67 while ((*ptr++ & 0x80) != 0); |
| 68 |
| 69 if (maxlen < ptr - *ptrptr) { |
| 70 NSMutableArray *byteStrs; |
| 71 const uint8_t *ptr2 = *ptrptr; |
| 72 |
| 73 byteStrs = [NSMutableArray array]; |
| 74 do { |
| 75 [byteStrs addObject:[NSString stringWithFormat:@"%02x", *ptr2]]; |
| 76 } while (++ptr2 < ptr); |
| 77 //NSLog(@"max uleb length now: %u (%@)", ptr - *ptrptr, [byteStrs compon
entsJoinedByString:@" "]); |
| 78 //NSLog(@"sizeof(uint64_t): %u, sizeof(uintptr_t): %u", sizeof(uint64_t)
, sizeof(uintptr_t)); |
| 79 maxlen = ptr - *ptrptr; |
| 80 } |
| 81 |
| 82 *ptrptr = ptr; |
| 83 return result; |
| 84 } |
| 85 |
| 86 static int64_t read_sleb128(const uint8_t **ptrptr, const uint8_t *end) |
| 87 { |
| 88 const uint8_t *ptr = *ptrptr; |
| 89 |
| 90 int64_t result = 0; |
| 91 int bit = 0; |
| 92 uint8_t byte; |
| 93 |
| 94 //NSLog(@"read_sleb128()"); |
| 95 do { |
| 96 if (ptr == end) { |
| 97 NSLog(@"Malformed sleb128"); |
| 98 exit(88); |
| 99 } |
| 100 |
| 101 byte = *ptr++; |
| 102 //NSLog(@"%02x", byte); |
| 103 result |= ((byte & 0x7f) << bit); |
| 104 bit += 7; |
| 105 } while ((byte & 0x80) != 0); |
| 106 |
| 107 //NSLog(@"result before sign extend: %ld", result); |
| 108 // sign extend negative numbers |
| 109 // This essentially clears out from -1 the low order bits we've already set,
and combines that with our bits. |
| 110 if ( (byte & 0x40) != 0 ) |
| 111 result |= (-1LL) << bit; |
| 112 |
| 113 //NSLog(@"result after sign extend: %ld", result); |
| 114 |
| 115 //NSLog(@"ptr before: %p, after: %p", *ptrptr, ptr); |
| 116 *ptrptr = ptr; |
| 117 return result; |
| 118 } |
| 119 |
| 120 static NSString *CDRebaseTypeString(uint8_t type) |
| 121 { |
| 122 switch (type) { |
| 123 case REBASE_TYPE_POINTER: return @"Pointer"; |
| 124 case REBASE_TYPE_TEXT_ABSOLUTE32: return @"Absolute 32"; |
| 125 case REBASE_TYPE_TEXT_PCREL32: return @"PC rel 32"; |
| 126 } |
| 127 |
| 128 return @"Unknown"; |
| 129 } |
| 130 |
| 131 static NSString *CDBindTypeString(uint8_t type) |
| 132 { |
| 133 switch (type) { |
| 134 case REBASE_TYPE_POINTER: return @"Pointer"; |
| 135 case REBASE_TYPE_TEXT_ABSOLUTE32: return @"Absolute 32"; |
| 136 case REBASE_TYPE_TEXT_PCREL32: return @"PC rel 32"; |
| 137 } |
| 138 |
| 139 return @"Unknown"; |
| 140 } |
| 141 |
| 142 // Need acces to: list of segments |
| 143 |
| 144 @implementation CDLCDyldInfo |
| 145 |
| 146 - (id)initWithDataCursor:(CDDataCursor *)cursor machOFile:(CDMachOFile *)aMachOF
ile; |
| 147 { |
| 148 if ([super initWithDataCursor:cursor machOFile:aMachOFile] == nil) |
| 149 return nil; |
| 150 |
| 151 dyldInfoCommand.cmd = [cursor readInt32]; |
| 152 dyldInfoCommand.cmdsize = [cursor readInt32]; |
| 153 |
| 154 dyldInfoCommand.rebase_off = [cursor readInt32]; |
| 155 dyldInfoCommand.rebase_size = [cursor readInt32]; |
| 156 dyldInfoCommand.bind_off = [cursor readInt32]; |
| 157 dyldInfoCommand.bind_size = [cursor readInt32]; |
| 158 dyldInfoCommand.weak_bind_off = [cursor readInt32]; |
| 159 dyldInfoCommand.weak_bind_size = [cursor readInt32]; |
| 160 dyldInfoCommand.lazy_bind_off = [cursor readInt32]; |
| 161 dyldInfoCommand.lazy_bind_size = [cursor readInt32]; |
| 162 dyldInfoCommand.export_off = [cursor readInt32]; |
| 163 dyldInfoCommand.export_size = [cursor readInt32]; |
| 164 |
| 165 #if 0 |
| 166 NSLog(@" cmdsize: %08x", dyldInfoCommand.cmdsize); |
| 167 NSLog(@" rebase_off: %08x", dyldInfoCommand.rebase_off); |
| 168 NSLog(@" rebase_size: %08x", dyldInfoCommand.rebase_size); |
| 169 NSLog(@" bind_off: %08x", dyldInfoCommand.bind_off); |
| 170 NSLog(@" bind_size: %08x", dyldInfoCommand.bind_size); |
| 171 NSLog(@" weak_bind_off: %08x", dyldInfoCommand.weak_bind_off); |
| 172 NSLog(@"weak_bind_size: %08x", dyldInfoCommand.weak_bind_size); |
| 173 NSLog(@" lazy_bind_off: %08x", dyldInfoCommand.lazy_bind_off); |
| 174 NSLog(@"lazy_bind_size: %08x", dyldInfoCommand.lazy_bind_size); |
| 175 NSLog(@" export_off: %08x", dyldInfoCommand.export_off); |
| 176 NSLog(@" export_size: %08x", dyldInfoCommand.export_size); |
| 177 #endif |
| 178 |
| 179 if ([aMachOFile uses64BitABI]) |
| 180 ptrSize = sizeof(uint64_t); |
| 181 else |
| 182 ptrSize = sizeof(uint32_t); |
| 183 |
| 184 symbolNamesByAddress = [[NSMutableDictionary alloc] init]; |
| 185 |
| 186 //[self logRebaseInfo]; |
| 187 [self logBindInfo]; // Acutally loads it for now. |
| 188 [self logWeakBindInfo]; |
| 189 //[self logLazyBindInfo]; |
| 190 //[self logExportedSymbols]; |
| 191 |
| 192 //NSLog(@"symbolNamesByAddress: %@", symbolNamesByAddress); |
| 193 |
| 194 return self; |
| 195 } |
| 196 |
| 197 - (void)dealloc; |
| 198 { |
| 199 [symbolNamesByAddress release]; |
| 200 |
| 201 [super dealloc]; |
| 202 } |
| 203 |
| 204 - (uint32_t)cmd; |
| 205 { |
| 206 return dyldInfoCommand.cmd; |
| 207 } |
| 208 |
| 209 - (uint32_t)cmdsize; |
| 210 { |
| 211 return dyldInfoCommand.cmdsize; |
| 212 } |
| 213 |
| 214 - (NSString *)symbolNameForAddress:(NSUInteger)address; |
| 215 { |
| 216 return [symbolNamesByAddress objectForKey:[NSNumber numberWithUnsignedIntege
r:address]]; |
| 217 } |
| 218 |
| 219 // |
| 220 // Rebasing |
| 221 // |
| 222 |
| 223 // address, slide, type |
| 224 // slide is constant throughout the loop |
| 225 - (void)logRebaseInfo; |
| 226 { |
| 227 const uint8_t *start, *end, *ptr; |
| 228 BOOL isDone = NO; |
| 229 NSArray *segments; |
| 230 uint64_t address; |
| 231 uint8_t type; |
| 232 NSUInteger rebaseCount = 0; |
| 233 |
| 234 segments = [nonretained_machOFile segments]; |
| 235 NSLog(@"segments: %@", segments); |
| 236 NSParameterAssert([segments count] > 0); |
| 237 |
| 238 address = [[segments objectAtIndex:0] vmaddr]; |
| 239 type = 0; |
| 240 |
| 241 NSLog(@"--------------------------------------------------------------------
--"); |
| 242 NSLog(@"rebase_off: %u, rebase_size: %u", dyldInfoCommand.rebase_off, dyldIn
foCommand.rebase_size); |
| 243 start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.rebase_off; |
| 244 end = start + dyldInfoCommand.rebase_size; |
| 245 |
| 246 NSLog(@"address: %016lx", address); |
| 247 ptr = start; |
| 248 while ((ptr < end) && isDone == NO) { |
| 249 uint8_t immediate, opcode; |
| 250 |
| 251 immediate = *ptr & REBASE_IMMEDIATE_MASK; |
| 252 opcode = *ptr & REBASE_OPCODE_MASK; |
| 253 ptr++; |
| 254 |
| 255 switch (opcode) { |
| 256 case REBASE_OPCODE_DONE: |
| 257 //NSLog(@"REBASE_OPCODE: DONE"); |
| 258 isDone = YES; |
| 259 break; |
| 260 |
| 261 case REBASE_OPCODE_SET_TYPE_IMM: |
| 262 //NSLog(@"REBASE_OPCODE: SET_TYPE_IMM, type
= 0x%x // %@", immediate, CDRebaseTypeString(immediate)); |
| 263 type = immediate; |
| 264 break; |
| 265 |
| 266 case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: { |
| 267 uint64_t val = read_uleb128(&ptr, end); |
| 268 |
| 269 //NSLog(@"REBASE_OPCODE: SET_SEGMENT_AND_OFFSET_ULEB, segme
nt index: %u, offset: %016lx", immediate, val); |
| 270 NSParameterAssert(immediate < [segments count]); |
| 271 address = [[segments objectAtIndex:immediate] vmaddr] + val; |
| 272 //NSLog(@" address: %016lx", address); |
| 273 break; |
| 274 } |
| 275 |
| 276 case REBASE_OPCODE_ADD_ADDR_ULEB: { |
| 277 uint64_t val = read_uleb128(&ptr, end); |
| 278 |
| 279 //NSLog(@"REBASE_OPCODE: ADD_ADDR_ULEB, addr
+= %016lx", val); |
| 280 address += val; |
| 281 //NSLog(@" address: %016lx", address); |
| 282 break; |
| 283 } |
| 284 |
| 285 case REBASE_OPCODE_ADD_ADDR_IMM_SCALED: |
| 286 // I expect sizeof(uintptr_t) == sizeof(uint64_t) |
| 287 //NSLog(@"REBASE_OPCODE: ADD_ADDR_IMM_SCALED, addr
+= %u * %u", immediate, sizeof(uint64_t)); |
| 288 address += immediate * ptrSize; |
| 289 //NSLog(@" address: %016lx", address); |
| 290 break; |
| 291 |
| 292 case REBASE_OPCODE_DO_REBASE_IMM_TIMES: { |
| 293 uint32_t index; |
| 294 |
| 295 //NSLog(@"REBASE_OPCODE: DO_REBASE_IMM_TIMES, count
: %u", immediate); |
| 296 for (index = 0; index < immediate; index++) { |
| 297 [self rebaseAddress:address type:type]; |
| 298 address += ptrSize; |
| 299 } |
| 300 rebaseCount += immediate; |
| 301 break; |
| 302 } |
| 303 |
| 304 case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: { |
| 305 uint64_t count, index; |
| 306 |
| 307 count = read_uleb128(&ptr, end); |
| 308 |
| 309 //NSLog(@"REBASE_OPCODE: DO_REBASE_ULEB_TIMES, count
: 0x%016lx", count); |
| 310 for (index = 0; index < count; index++) { |
| 311 [self rebaseAddress:address type:type]; |
| 312 address += ptrSize; |
| 313 } |
| 314 rebaseCount += count; |
| 315 break; |
| 316 } |
| 317 |
| 318 case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: { |
| 319 uint64_t val; |
| 320 |
| 321 val = read_uleb128(&ptr, end); |
| 322 // --------------------------------------------------------: |
| 323 //NSLog(@"REBASE_OPCODE: DO_REBASE_ADD_ADDR_ULEB, addr
+= 0x%016lx", val); |
| 324 [self rebaseAddress:address type:type]; |
| 325 address += ptrSize + val; |
| 326 rebaseCount++; |
| 327 break; |
| 328 } |
| 329 |
| 330 case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: { |
| 331 uint64_t count, skip, index; |
| 332 |
| 333 count = read_uleb128(&ptr, end); |
| 334 skip = read_uleb128(&ptr, end); |
| 335 //NSLog(@"REBASE_OPCODE: DO_REBASE_ULEB_TIMES_SKIPPING_ULEB, count
: %016lx, skip: %016lx", count, skip); |
| 336 for (index = 0; index < count; index++) { |
| 337 [self rebaseAddress:address type:type]; |
| 338 address += ptrSize + skip; |
| 339 } |
| 340 rebaseCount += count; |
| 341 break; |
| 342 } |
| 343 |
| 344 default: |
| 345 NSLog(@"Unknown opcode op: %x, imm: %x", opcode, immediate); |
| 346 exit(99); |
| 347 } |
| 348 } |
| 349 |
| 350 NSLog(@" ptr: %p, end: %p, bytes left over: %u", ptr, end, end - ptr); |
| 351 NSLog(@" rebaseCount: %lu", rebaseCount); |
| 352 NSLog(@"--------------------------------------------------------------------
--"); |
| 353 } |
| 354 |
| 355 - (void)rebaseAddress:(uint64_t)address type:(uint8_t)type; |
| 356 { |
| 357 //NSLog(@" Rebase 0x%016lx, type: %x (%@)", address, type, CDRebaseTypeSt
ring(type)); |
| 358 } |
| 359 |
| 360 // |
| 361 // Binding |
| 362 // |
| 363 |
| 364 // From mach-o/loader.h: |
| 365 // Dyld binds an image during the loading process, if the image requires any poi
nters to be initialized to symbols in other images. |
| 366 // Conceptually the bind information is a table of tuples: |
| 367 // <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend> |
| 368 |
| 369 - (void)logBindInfo; |
| 370 { |
| 371 const uint8_t *start, *end; |
| 372 |
| 373 if (debugBindOps) { |
| 374 NSLog(@"----------------------------------------------------------------
------"); |
| 375 NSLog(@"bind_off: %u, bind_size: %u", dyldInfoCommand.bind_off, dyldInfo
Command.bind_size); |
| 376 } |
| 377 start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.bind_off; |
| 378 end = start + dyldInfoCommand.bind_size; |
| 379 |
| 380 [self logBindOps:start end:end isLazy:NO]; |
| 381 } |
| 382 |
| 383 - (void)logWeakBindInfo; |
| 384 { |
| 385 const uint8_t *start, *end; |
| 386 |
| 387 if (debugBindOps) { |
| 388 NSLog(@"----------------------------------------------------------------
------"); |
| 389 NSLog(@"weak_bind_off: %u, weak_bind_size: %u", dyldInfoCommand.weak_bin
d_off, dyldInfoCommand.weak_bind_size); |
| 390 } |
| 391 start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.weak_bind_o
ff; |
| 392 end = start + dyldInfoCommand.weak_bind_size; |
| 393 |
| 394 [self logBindOps:start end:end isLazy:NO]; |
| 395 } |
| 396 |
| 397 - (void)logLazyBindInfo; |
| 398 { |
| 399 const uint8_t *start, *end; |
| 400 |
| 401 if (debugBindOps) { |
| 402 NSLog(@"----------------------------------------------------------------
------"); |
| 403 NSLog(@"lazy_bind_off: %u, lazy_bind_size: %u", dyldInfoCommand.lazy_bin
d_off, dyldInfoCommand.lazy_bind_size); |
| 404 } |
| 405 start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.lazy_bind_o
ff; |
| 406 end = start + dyldInfoCommand.lazy_bind_size; |
| 407 |
| 408 [self logBindOps:start end:end isLazy:YES]; |
| 409 } |
| 410 |
| 411 - (void)logBindOps:(const uint8_t *)start end:(const uint8_t *)end isLazy:(BOOL)
isLazy; |
| 412 { |
| 413 BOOL isDone = NO; |
| 414 NSUInteger bindCount = 0; |
| 415 |
| 416 const uint8_t *ptr; |
| 417 NSArray *segments; |
| 418 uint64_t address; |
| 419 int64_t libraryOrdinal = 0; |
| 420 uint8_t type = 0; |
| 421 int64_t addend = 0; |
| 422 uint8_t segmentIndex = 0; |
| 423 const char *symbolName = NULL; |
| 424 uint8_t symbolFlags = 0; |
| 425 |
| 426 segments = [nonretained_machOFile segments]; |
| 427 //NSLog(@"segments: %@", segments); |
| 428 NSParameterAssert([segments count] > 0); |
| 429 |
| 430 address = [[segments objectAtIndex:0] vmaddr]; |
| 431 |
| 432 ptr = start; |
| 433 while ((ptr < end) && isDone == NO) { |
| 434 uint8_t immediate, opcode; |
| 435 |
| 436 immediate = *ptr & BIND_IMMEDIATE_MASK; |
| 437 opcode = *ptr & BIND_OPCODE_MASK; |
| 438 ptr++; |
| 439 |
| 440 switch (opcode) { |
| 441 case BIND_OPCODE_DONE: |
| 442 if (debugBindOps) NSLog(@"BIND_OPCODE: DONE"); |
| 443 |
| 444 // The lazy bindings have one of these at the end of each bind. |
| 445 if (isLazy == NO) |
| 446 isDone = YES; |
| 447 break; |
| 448 |
| 449 case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: |
| 450 libraryOrdinal = immediate; |
| 451 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_DYLIB_ORDINAL_IMM,
libraryOrdinal = %ld", libraryOrdinal); |
| 452 break; |
| 453 |
| 454 case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: |
| 455 libraryOrdinal = read_uleb128(&ptr, end); |
| 456 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_DYLIB_ORDINAL_ULEB,
libraryOrdinal = %ld", libraryOrdinal); |
| 457 break; |
| 458 |
| 459 case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: { |
| 460 // Special means negative |
| 461 if (immediate == 0) |
| 462 libraryOrdinal = 0; |
| 463 else { |
| 464 int8_t val = immediate | BIND_OPCODE_MASK; // This sign extend
s the value |
| 465 |
| 466 libraryOrdinal = val; |
| 467 } |
| 468 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_DYLIB_SPECIAL_IMM,
libraryOrdinal = %ld", libraryOrdinal); |
| 469 break; |
| 470 } |
| 471 |
| 472 case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: |
| 473 symbolName = (const char *)ptr; |
| 474 symbolFlags = immediate; |
| 475 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_SYMBOL_TRAILING_FLAGS_I
MM, flags: %02x, str = %s", symbolFlags, symbolName); |
| 476 while (*ptr != 0) |
| 477 ptr++; |
| 478 |
| 479 ptr++; // skip the trailing zero |
| 480 |
| 481 break; |
| 482 |
| 483 case BIND_OPCODE_SET_TYPE_IMM: |
| 484 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_TYPE_IMM,
type = %u (%@)", immediate, CDBindTypeString(immediate)); |
| 485 type = immediate; |
| 486 break; |
| 487 |
| 488 case BIND_OPCODE_SET_ADDEND_SLEB: |
| 489 addend = read_sleb128(&ptr, end); |
| 490 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_ADDEND_SLEB,
addend = %ld", addend); |
| 491 break; |
| 492 |
| 493 case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: { |
| 494 uint64_t val; |
| 495 |
| 496 segmentIndex = immediate; |
| 497 val = read_uleb128(&ptr, end); |
| 498 if (debugBindOps) NSLog(@"BIND_OPCODE: SET_SEGMENT_AND_OFFSET_ULEB
, segmentIndex: %u, offset: 0x%016lx", segmentIndex, val); |
| 499 address = [[segments objectAtIndex:segmentIndex] vmaddr] + val; |
| 500 if (debugBindOps) NSLog(@" address = 0x%016lx", address); |
| 501 break; |
| 502 } |
| 503 |
| 504 case BIND_OPCODE_ADD_ADDR_ULEB: { |
| 505 uint64_t val; |
| 506 |
| 507 val = read_uleb128(&ptr, end); |
| 508 if (debugBindOps) NSLog(@"BIND_OPCODE: ADD_ADDR_ULEB,
addr += 0x%016lx", val); |
| 509 address += val; |
| 510 break; |
| 511 } |
| 512 |
| 513 case BIND_OPCODE_DO_BIND: |
| 514 if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND"); |
| 515 [self bindAddress:address type:type symbolName:symbolName flags:sy
mbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
| 516 address += ptrSize; |
| 517 bindCount++; |
| 518 break; |
| 519 |
| 520 case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: { |
| 521 uint64_t val; |
| 522 |
| 523 val = read_uleb128(&ptr, end); |
| 524 if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND_ADD_ADDR_ULEB,
address += %016lx", val); |
| 525 [self bindAddress:address type:type symbolName:symbolName flags:sy
mbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
| 526 address += ptrSize + val; |
| 527 bindCount++; |
| 528 break; |
| 529 } |
| 530 |
| 531 case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: |
| 532 if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND_ADD_ADDR_IMM_SCALED
, address += %u * %u", immediate, ptrSize); |
| 533 [self bindAddress:address type:type symbolName:symbolName flags:sy
mbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
| 534 address += ptrSize + immediate * ptrSize; |
| 535 bindCount++; |
| 536 break; |
| 537 |
| 538 case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: { |
| 539 uint64_t count, skip, index; |
| 540 |
| 541 count = read_uleb128(&ptr, end); |
| 542 skip = read_uleb128(&ptr, end); |
| 543 if (debugBindOps) NSLog(@"BIND_OPCODE: DO_BIND_ULEB_TIMES_SKIPPING
_ULEB, count: %016lx, skip: %016lx", count, skip); |
| 544 for (index = 0; index < count; index++) { |
| 545 [self bindAddress:address type:type symbolName:symbolName flag
s:symbolFlags addend:addend libraryOrdinal:libraryOrdinal]; |
| 546 address += ptrSize + skip; |
| 547 } |
| 548 bindCount += count; |
| 549 break; |
| 550 } |
| 551 |
| 552 default: |
| 553 NSLog(@"Unknown opcode op: %x, imm: %x", opcode, immediate); |
| 554 exit(99); |
| 555 } |
| 556 } |
| 557 |
| 558 if (debugBindOps) { |
| 559 NSLog(@" ptr: %p, end: %p, bytes left over: %u", ptr, end, end - ptr)
; |
| 560 NSLog(@" bindCount: %lu", bindCount); |
| 561 NSLog(@"----------------------------------------------------------------
------"); |
| 562 } |
| 563 } |
| 564 |
| 565 - (void)bindAddress:(uint64_t)address type:(uint8_t)type symbolName:(const char
*)symbolName flags:(uint8_t)flags |
| 566 addend:(int64_t)addend libraryOrdinal:(int64_t)libraryOrdinal; |
| 567 { |
| 568 NSNumber *key; |
| 569 NSString *str; |
| 570 |
| 571 #if 0 |
| 572 NSLog(@" Bind address: %016lx, type: 0x%02x, flags: %02x, addend: %016lx,
libraryOrdinal: %ld, symbolName: %s", |
| 573 address, type, flags, addend, libraryOrdinal, symbolName); |
| 574 #endif |
| 575 |
| 576 key = [NSNumber numberWithUnsignedInteger:address]; // I don't think 32-bit
will dump 64-bit stuff. |
| 577 str = [[NSString alloc] initWithUTF8String:symbolName]; |
| 578 [symbolNamesByAddress setObject:str forKey:key]; |
| 579 [str release]; |
| 580 } |
| 581 |
| 582 // |
| 583 // Exported symbols |
| 584 // |
| 585 |
| 586 - (void)logExportedSymbols; |
| 587 { |
| 588 const uint8_t *start, *end; |
| 589 |
| 590 if (debugExportedSymbols) { |
| 591 NSLog(@"----------------------------------------------------------------
------"); |
| 592 NSLog(@"export_off: %u, export_size: %u", dyldInfoCommand.export_off, dy
ldInfoCommand.export_size); |
| 593 NSLog(@"hexdump -Cv -s %u -n %u", dyldInfoCommand.export_off, dyldInfoCo
mmand.export_size); |
| 594 } |
| 595 |
| 596 start = [nonretained_machOFile machODataBytes] + dyldInfoCommand.export_off; |
| 597 end = start + dyldInfoCommand.export_size; |
| 598 |
| 599 NSLog(@" Type Flags Offset Name"); |
| 600 NSLog(@"------------- ----- ---------------- ----"); |
| 601 [self printSymbols:start end:end prefix:@"" offset:0]; |
| 602 } |
| 603 |
| 604 - (void)printSymbols:(const uint8_t *)start end:(const uint8_t *)end prefix:(NSS
tring *)prefix offset:(uint32_t)offset; |
| 605 { |
| 606 uint8_t terminalSize; |
| 607 const uint8_t *ptr, *tptr; |
| 608 uint8_t childCount, index; |
| 609 |
| 610 //NSLog(@" > %s, %p-%p, offset: %lx = %p", _cmd, start, end, offset, start +
offset); |
| 611 |
| 612 ptr = start + offset; |
| 613 NSParameterAssert(ptr < end); |
| 614 |
| 615 terminalSize = *ptr++; |
| 616 tptr = ptr; |
| 617 //NSLog(@"terminalSize: %u", terminalSize); |
| 618 |
| 619 ptr += terminalSize; |
| 620 |
| 621 childCount = *ptr++; |
| 622 |
| 623 if (terminalSize > 0) { |
| 624 uint64_t flags; |
| 625 uint8_t kind; |
| 626 |
| 627 //NSLog(@"symbol: '%@', terminalSize: %u", prefix, terminalSize); |
| 628 flags = read_uleb128(&tptr, end); |
| 629 kind = flags & EXPORT_SYMBOL_FLAGS_KIND_MASK; |
| 630 if (kind == EXPORT_SYMBOL_FLAGS_KIND_REGULAR) { |
| 631 uint64_t offset; |
| 632 |
| 633 offset = read_uleb128(&tptr, end); |
| 634 NSLog(@" Regular: %04x %016lx %@", flags, offset, prefix); |
| 635 //NSLog(@" Regular: %04x 0x%08x %@", flags, offset, prefix); |
| 636 } else if (kind == EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL) { |
| 637 NSLog(@"Thread Local: %04x %@, terminalSize: %u",
flags, prefix, terminalSize); |
| 638 } else { |
| 639 NSLog(@" Unknown: %04x %x, name: %@, terminalSize: %u", flags,
kind, prefix, terminalSize); |
| 640 } |
| 641 } |
| 642 |
| 643 for (index = 0; index < childCount; index++) { |
| 644 const uint8_t *edgeStart = ptr; |
| 645 uint32_t length; |
| 646 uint64_t nodeOffset; |
| 647 |
| 648 while (*ptr++ != 0) |
| 649 ; |
| 650 |
| 651 length = ptr - edgeStart; |
| 652 //NSLog(@"edge length: %u, edge: '%s'", length, edgeStart); |
| 653 nodeOffset = read_uleb128(&ptr, end); |
| 654 //NSLog(@"node offset: %lx", nodeOffset); |
| 655 |
| 656 [self printSymbols:start end:end prefix:[NSString stringWithFormat:@"%@%
s", prefix, edgeStart] offset:nodeOffset]; |
| 657 } |
| 658 |
| 659 //NSLog(@"< %s, %p-%p, offset: %lx = %p", _cmd, start, end, offset, start +
offset); |
| 660 } |
| 661 |
| 662 @end |
OLD | NEW |