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 "CDObjectiveC2Processor64.h" |
| 7 |
| 8 #import "CDMachOFile.h" |
| 9 #import "CDSection.h" |
| 10 #import "CDLCSegment.h" |
| 11 #import "CDDataCursor.h" |
| 12 #import "CDOCClass.h" |
| 13 #import "CDOCMethod.h" |
| 14 #import "CDOCIvar.h" |
| 15 #import "NSArray-Extensions.h" |
| 16 #import "CDLCSymbolTable.h" |
| 17 #import "CDOCCategory.h" |
| 18 #import "CDClassDump.h" |
| 19 #import "CDSymbol.h" |
| 20 #import "CDOCProperty.h" |
| 21 #import "cd_objc2.h" |
| 22 |
| 23 @implementation CDObjectiveC2Processor64 |
| 24 |
| 25 - (void)loadProtocols; |
| 26 { |
| 27 CDLCSegment *segment; |
| 28 CDSection *section; |
| 29 NSData *sectionData; |
| 30 CDDataCursor *cursor; |
| 31 |
| 32 segment = [machOFile segmentWithName:@"__DATA"]; |
| 33 section = [segment sectionWithName:@"__objc_protolist"]; |
| 34 sectionData = [section data]; |
| 35 |
| 36 cursor = [[CDDataCursor alloc] initWithData:sectionData]; |
| 37 [cursor setByteOrder:[machOFile byteOrder]]; |
| 38 while ([cursor isAtEnd] == NO) |
| 39 [self protocolAtAddress:[cursor readInt64]]; |
| 40 [cursor release]; |
| 41 |
| 42 [self createUniquedProtocols]; |
| 43 } |
| 44 |
| 45 - (void)loadClasses; |
| 46 { |
| 47 CDLCSegment *segment; |
| 48 CDSection *section; |
| 49 NSData *sectionData; |
| 50 CDDataCursor *cursor; |
| 51 |
| 52 segment = [machOFile segmentWithName:@"__DATA"]; |
| 53 section = [segment sectionWithName:@"__objc_classlist"]; |
| 54 sectionData = [section data]; |
| 55 |
| 56 cursor = [[CDDataCursor alloc] initWithData:sectionData]; |
| 57 [cursor setByteOrder:[machOFile byteOrder]]; |
| 58 while ([cursor isAtEnd] == NO) { |
| 59 uint64_t val; |
| 60 CDOCClass *aClass; |
| 61 |
| 62 val = [cursor readInt64]; |
| 63 aClass = [self loadClassAtAddress:val]; |
| 64 if (aClass != nil) { |
| 65 [classes addObject:aClass]; |
| 66 [classesByAddress setObject:aClass forKey:[NSNumber numberWithUnsign
edInteger:val]]; |
| 67 } |
| 68 } |
| 69 |
| 70 [cursor release]; |
| 71 } |
| 72 |
| 73 - (void)loadCategories; |
| 74 { |
| 75 CDLCSegment *segment; |
| 76 CDSection *section; |
| 77 NSData *sectionData; |
| 78 CDDataCursor *cursor; |
| 79 |
| 80 segment = [machOFile segmentWithName:@"__DATA"]; |
| 81 section = [segment sectionWithName:@"__objc_catlist"]; |
| 82 sectionData = [section data]; |
| 83 |
| 84 cursor = [[CDDataCursor alloc] initWithData:sectionData]; |
| 85 [cursor setByteOrder:[machOFile byteOrder]]; |
| 86 while ([cursor isAtEnd] == NO) { |
| 87 CDOCCategory *category; |
| 88 |
| 89 category = [self loadCategoryAtAddress:[cursor readInt64]]; |
| 90 if (category != nil) |
| 91 [categories addObject:category]; |
| 92 } |
| 93 |
| 94 [cursor release]; |
| 95 } |
| 96 |
| 97 - (CDOCProtocol *)protocolAtAddress:(uint64_t)address; |
| 98 { |
| 99 NSNumber *key; |
| 100 CDOCProtocol *protocol; |
| 101 |
| 102 if (address == 0) |
| 103 return nil; |
| 104 |
| 105 key = [NSNumber numberWithUnsignedInteger:address]; |
| 106 protocol = [protocolsByAddress objectForKey:key]; |
| 107 if (protocol == nil) { |
| 108 struct cd_objc2_protocol_64 objc2Protocol; |
| 109 CDDataCursor *cursor; |
| 110 NSString *str; |
| 111 |
| 112 protocol = [[[CDOCProtocol alloc] init] autorelease]; |
| 113 [protocolsByAddress setObject:protocol forKey:key]; |
| 114 |
| 115 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 116 [cursor setByteOrder:[machOFile byteOrder]]; |
| 117 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 118 NSParameterAssert([cursor offset] != 0); |
| 119 |
| 120 objc2Protocol.isa = [cursor readInt64]; |
| 121 objc2Protocol.name = [cursor readInt64]; |
| 122 objc2Protocol.protocols = [cursor readInt64]; |
| 123 objc2Protocol.instanceMethods = [cursor readInt64]; |
| 124 objc2Protocol.classMethods = [cursor readInt64]; |
| 125 objc2Protocol.optionalInstanceMethods = [cursor readInt64]; |
| 126 objc2Protocol.optionalClassMethods = [cursor readInt64]; |
| 127 objc2Protocol.instanceProperties = [cursor readInt64]; |
| 128 |
| 129 //NSLog(@"----------------------------------------"); |
| 130 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Protocol.isa, objc2Protocol
.name, objc2Protocol.protocols, objc2Protocol.instanceMethods); |
| 131 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Protocol.classMethods, objc
2Protocol.optionalInstanceMethods, objc2Protocol.optionalClassMethods, objc2Prot
ocol.instanceProperties); |
| 132 |
| 133 str = [machOFile stringAtAddress:objc2Protocol.name]; |
| 134 [protocol setName:str]; |
| 135 |
| 136 if (objc2Protocol.protocols != 0) { |
| 137 uint64_t count, index; |
| 138 |
| 139 [cursor setOffset:[machOFile dataOffsetForAddress:objc2Protocol.prot
ocols]]; |
| 140 count = [cursor readInt64]; |
| 141 for (index = 0; index < count; index++) { |
| 142 uint64_t val; |
| 143 CDOCProtocol *anotherProtocol; |
| 144 |
| 145 val = [cursor readInt64]; |
| 146 anotherProtocol = [self protocolAtAddress:val]; |
| 147 if (anotherProtocol != nil) { |
| 148 [protocol addProtocol:anotherProtocol]; |
| 149 } else { |
| 150 NSLog(@"Note: another protocol was nil."); |
| 151 } |
| 152 } |
| 153 } |
| 154 |
| 155 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2Protocol.inst
anceMethods]) |
| 156 [protocol addInstanceMethod:method]; |
| 157 |
| 158 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2Protocol.clas
sMethods]) |
| 159 [protocol addClassMethod:method]; |
| 160 |
| 161 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2Protocol.opti
onalInstanceMethods]) |
| 162 [protocol addOptionalInstanceMethod:method]; |
| 163 |
| 164 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2Protocol.opti
onalClassMethods]) |
| 165 [protocol addOptionalClassMethod:method]; |
| 166 |
| 167 for (CDOCProperty *property in [self loadPropertiesAtAddress:objc2Protoc
ol.instanceProperties]) |
| 168 [protocol addProperty:property]; |
| 169 |
| 170 [cursor release]; |
| 171 } |
| 172 |
| 173 return protocol; |
| 174 } |
| 175 |
| 176 - (CDOCCategory *)loadCategoryAtAddress:(uint64_t)address; |
| 177 { |
| 178 struct cd_objc2_category_64 objc2Category; |
| 179 CDDataCursor *cursor; |
| 180 NSString *str; |
| 181 CDOCCategory *category; |
| 182 |
| 183 if (address == 0) |
| 184 return nil; |
| 185 |
| 186 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 187 [cursor setByteOrder:[machOFile byteOrder]]; |
| 188 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 189 NSParameterAssert([cursor offset] != 0); |
| 190 |
| 191 objc2Category.name = [cursor readInt64]; |
| 192 objc2Category.class = [cursor readInt64]; |
| 193 objc2Category.instanceMethods = [cursor readInt64]; |
| 194 objc2Category.classMethods = [cursor readInt64]; |
| 195 objc2Category.protocols = [cursor readInt64]; |
| 196 objc2Category.instanceProperties = [cursor readInt64]; |
| 197 objc2Category.v7 = [cursor readInt64]; |
| 198 objc2Category.v8 = [cursor readInt64]; |
| 199 //NSLog(@"----------------------------------------"); |
| 200 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Category.name, objc2Category.cl
ass, objc2Category.instanceMethods, objc2Category.classMethods); |
| 201 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Category.protocols, objc2Catego
ry.instanceProperties, objc2Category.v7, objc2Category.v8); |
| 202 |
| 203 category = [[[CDOCCategory alloc] init] autorelease]; |
| 204 str = [machOFile stringAtAddress:objc2Category.name]; |
| 205 [category setName:str]; |
| 206 |
| 207 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2Category.instance
Methods]) |
| 208 [category addInstanceMethod:method]; |
| 209 |
| 210 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2Category.classMet
hods]) |
| 211 [category addClassMethod:method]; |
| 212 |
| 213 for (CDOCProtocol *protocol in [self uniquedProtocolListAtAddress:objc2Categ
ory.protocols]) |
| 214 [category addProtocol:protocol]; |
| 215 |
| 216 for (CDOCProperty *property in [self loadPropertiesAtAddress:objc2Category.i
nstanceProperties]) |
| 217 [category addProperty:property]; |
| 218 |
| 219 { |
| 220 uint64_t classNameAddress = address + sizeof(objc2Category.name); |
| 221 |
| 222 if ([machOFile hasRelocationEntryForAddress2:classNameAddress]) { |
| 223 [category setClassName:[machOFile externalClassNameForAddress2:class
NameAddress]]; |
| 224 //NSLog(@"category: got external class name (2): %@", [category clas
sName]); |
| 225 } else if ([machOFile hasRelocationEntryForAddress:classNameAddress]) { |
| 226 [category setClassName:[machOFile externalClassNameForAddress:classN
ameAddress]]; |
| 227 //NSLog(@"category: got external class name (1): %@", [aClass classN
ame]); |
| 228 } else if (objc2Category.class != 0) { |
| 229 CDOCClass *aClass; |
| 230 |
| 231 aClass = [classesByAddress objectForKey:[NSNumber numberWithUnsigned
Integer:objc2Category.class]]; |
| 232 [category setClassName:[aClass name]]; |
| 233 } |
| 234 } |
| 235 |
| 236 [cursor release]; |
| 237 |
| 238 return category; |
| 239 } |
| 240 |
| 241 - (CDOCClass *)loadClassAtAddress:(uint64_t)address; |
| 242 { |
| 243 struct cd_objc2_class_64 objc2Class; |
| 244 struct cd_objc2_class_ro_t_64 objc2ClassData; |
| 245 CDDataCursor *cursor; |
| 246 NSString *str; |
| 247 CDOCClass *aClass; |
| 248 |
| 249 if (address == 0) |
| 250 return nil; |
| 251 |
| 252 //NSLog(@"%s, address=%016lx", _cmd, address); |
| 253 |
| 254 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 255 [cursor setByteOrder:[machOFile byteOrder]]; |
| 256 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 257 NSParameterAssert([cursor offset] != 0); |
| 258 |
| 259 objc2Class.isa = [cursor readInt64]; |
| 260 objc2Class.superclass = [cursor readInt64]; |
| 261 objc2Class.cache = [cursor readInt64]; |
| 262 objc2Class.vtable = [cursor readInt64]; |
| 263 objc2Class.data = [cursor readInt64]; |
| 264 objc2Class.reserved1 = [cursor readInt64]; |
| 265 objc2Class.reserved2 = [cursor readInt64]; |
| 266 objc2Class.reserved3 = [cursor readInt64]; |
| 267 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Class.isa, objc2Class.superclas
s, objc2Class.cache, objc2Class.vtable); |
| 268 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Class.data, objc2Class.reserved
1, objc2Class.reserved2, objc2Class.reserved3); |
| 269 |
| 270 NSParameterAssert(objc2Class.data != 0); |
| 271 [cursor setOffset:[machOFile dataOffsetForAddress:objc2Class.data]]; |
| 272 objc2ClassData.flags = [cursor readInt32]; |
| 273 objc2ClassData.instanceStart = [cursor readInt32]; |
| 274 objc2ClassData.instanceSize = [cursor readInt32]; |
| 275 objc2ClassData.reserved = [cursor readInt32]; |
| 276 |
| 277 objc2ClassData.ivarLayout = [cursor readInt64]; |
| 278 objc2ClassData.name = [cursor readInt64]; |
| 279 objc2ClassData.baseMethods = [cursor readInt64]; |
| 280 objc2ClassData.baseProtocols = [cursor readInt64]; |
| 281 objc2ClassData.ivars = [cursor readInt64]; |
| 282 objc2ClassData.weakIvarLayout = [cursor readInt64]; |
| 283 objc2ClassData.baseProperties = [cursor readInt64]; |
| 284 |
| 285 //NSLog(@"%08x %08x %08x %08x", objc2ClassData.flags, objc2ClassData.instanc
eStart, objc2ClassData.instanceSize, objc2ClassData.reserved); |
| 286 |
| 287 //NSLog(@"%016lx %016lx %016lx %016lx", objc2ClassData.ivarLayout, objc2Clas
sData.name, objc2ClassData.baseMethods, objc2ClassData.baseProtocols); |
| 288 //NSLog(@"%016lx %016lx %016lx %016lx", objc2ClassData.ivars, objc2ClassData
.weakIvarLayout, objc2ClassData.baseProperties); |
| 289 str = [machOFile stringAtAddress:objc2ClassData.name]; |
| 290 //NSLog(@"name = %@", str); |
| 291 |
| 292 aClass = [[[CDOCClass alloc] init] autorelease]; |
| 293 [aClass setName:str]; |
| 294 |
| 295 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2ClassData.baseMet
hods]) |
| 296 [aClass addInstanceMethod:method]; |
| 297 |
| 298 [aClass setIvars:[self loadIvarsAtAddress:objc2ClassData.ivars]]; |
| 299 |
| 300 [cursor release]; |
| 301 |
| 302 { |
| 303 CDSymbol *classSymbol = [[machOFile symbolTable] symbolForClass:str]; |
| 304 |
| 305 if (classSymbol != nil) |
| 306 aClass.isExported = [classSymbol isExternal]; |
| 307 } |
| 308 |
| 309 { |
| 310 uint64_t classNameAddress = address + sizeof(objc2Class.isa); |
| 311 |
| 312 if ([machOFile hasRelocationEntryForAddress2:classNameAddress]) { |
| 313 [aClass setSuperClassName:[machOFile externalClassNameForAddress2:cl
assNameAddress]]; |
| 314 //NSLog(@"class: got external class name (2): %@", [aClass superClas
sName]); |
| 315 } else if ([machOFile hasRelocationEntryForAddress:classNameAddress]) { |
| 316 [aClass setSuperClassName:[machOFile externalClassNameForAddress:cla
ssNameAddress]]; |
| 317 //NSLog(@"class: got external class name (1): %@", [aClass superClas
sName]); |
| 318 } else if (objc2Class.superclass != 0) { |
| 319 CDOCClass *sc; |
| 320 |
| 321 sc = [self loadClassAtAddress:objc2Class.superclass]; |
| 322 [aClass setSuperClassName:[sc name]]; |
| 323 } |
| 324 } |
| 325 |
| 326 for (CDOCMethod *method in [self loadMethodsOfMetaClassAtAddress:objc2Class.
isa]) |
| 327 [aClass addClassMethod:method]; |
| 328 |
| 329 // Process protocols |
| 330 for (CDOCProtocol *protocol in [self uniquedProtocolListAtAddress:objc2Class
Data.baseProtocols]) |
| 331 [aClass addProtocol:protocol]; |
| 332 |
| 333 for (CDOCProperty *property in [self loadPropertiesAtAddress:objc2ClassData.
baseProperties]) |
| 334 [aClass addProperty:property]; |
| 335 |
| 336 return aClass; |
| 337 } |
| 338 |
| 339 - (NSArray *)loadPropertiesAtAddress:(uint64_t)address; |
| 340 { |
| 341 NSMutableArray *properties; |
| 342 |
| 343 properties = [NSMutableArray array]; |
| 344 if (address != 0) { |
| 345 CDDataCursor *cursor; |
| 346 struct cd_objc2_list_header listHeader; |
| 347 uint32_t index; |
| 348 |
| 349 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 350 [cursor setByteOrder:[machOFile byteOrder]]; |
| 351 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 352 NSParameterAssert([cursor offset] != 0); |
| 353 //NSLog(@"property list data offset: %lu", [cursor offset]); |
| 354 |
| 355 listHeader.entsize = [cursor readInt32]; |
| 356 listHeader.count = [cursor readInt32]; |
| 357 NSParameterAssert(listHeader.entsize == 16); |
| 358 |
| 359 for (index = 0; index < listHeader.count; index++) { |
| 360 struct cd_objc2_property_64 objc2Property; |
| 361 NSString *name, *attributes; |
| 362 CDOCProperty *property; |
| 363 |
| 364 objc2Property.name = [cursor readInt64]; |
| 365 objc2Property.attributes = [cursor readInt64]; |
| 366 name = [machOFile stringAtAddress:objc2Property.name]; |
| 367 attributes = [machOFile stringAtAddress:objc2Property.attributes]; |
| 368 |
| 369 property = [[CDOCProperty alloc] initWithName:name attributes:attrib
utes]; |
| 370 [properties addObject:property]; |
| 371 [property release]; |
| 372 } |
| 373 |
| 374 [cursor release]; |
| 375 } |
| 376 |
| 377 return properties; |
| 378 } |
| 379 |
| 380 // This just gets the methods. |
| 381 - (NSArray *)loadMethodsOfMetaClassAtAddress:(uint64_t)address; |
| 382 { |
| 383 struct cd_objc2_class_64 objc2Class; |
| 384 struct cd_objc2_class_ro_t_64 objc2ClassData; |
| 385 CDDataCursor *cursor; |
| 386 |
| 387 if (address == 0) |
| 388 return nil; |
| 389 |
| 390 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 391 [cursor setByteOrder:[machOFile byteOrder]]; |
| 392 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 393 NSParameterAssert([cursor offset] != 0); |
| 394 |
| 395 objc2Class.isa = [cursor readInt64]; |
| 396 objc2Class.superclass = [cursor readInt64]; |
| 397 objc2Class.cache = [cursor readInt64]; |
| 398 objc2Class.vtable = [cursor readInt64]; |
| 399 objc2Class.data = [cursor readInt64]; |
| 400 objc2Class.reserved1 = [cursor readInt64]; |
| 401 objc2Class.reserved2 = [cursor readInt64]; |
| 402 objc2Class.reserved3 = [cursor readInt64]; |
| 403 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Class.isa, objc2Class.superclas
s, objc2Class.cache, objc2Class.vtable); |
| 404 //NSLog(@"%016lx %016lx %016lx %016lx", objc2Class.data, objc2Class.reserved
1, objc2Class.reserved2, objc2Class.reserved3); |
| 405 |
| 406 NSParameterAssert(objc2Class.data != 0); |
| 407 [cursor setOffset:[machOFile dataOffsetForAddress:objc2Class.data]]; |
| 408 objc2ClassData.flags = [cursor readInt32]; |
| 409 objc2ClassData.instanceStart = [cursor readInt32]; |
| 410 objc2ClassData.instanceSize = [cursor readInt32]; |
| 411 objc2ClassData.reserved = [cursor readInt32]; |
| 412 |
| 413 objc2ClassData.ivarLayout = [cursor readInt64]; |
| 414 objc2ClassData.name = [cursor readInt64]; |
| 415 objc2ClassData.baseMethods = [cursor readInt64]; |
| 416 objc2ClassData.baseProtocols = [cursor readInt64]; |
| 417 objc2ClassData.ivars = [cursor readInt64]; |
| 418 objc2ClassData.weakIvarLayout = [cursor readInt64]; |
| 419 objc2ClassData.baseProperties = [cursor readInt64]; |
| 420 |
| 421 [cursor release]; |
| 422 |
| 423 return [self loadMethodsAtAddress:objc2ClassData.baseMethods]; |
| 424 } |
| 425 |
| 426 - (NSArray *)loadMethodsAtAddress:(uint64_t)address; |
| 427 { |
| 428 NSMutableArray *methods; |
| 429 |
| 430 methods = [NSMutableArray array]; |
| 431 |
| 432 if (address != 0) { |
| 433 CDDataCursor *cursor; |
| 434 struct cd_objc2_list_header listHeader; |
| 435 uint32_t index; |
| 436 |
| 437 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 438 [cursor setByteOrder:[machOFile byteOrder]]; |
| 439 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 440 NSParameterAssert([cursor offset] != 0); |
| 441 //NSLog(@"method list data offset: %lu", [cursor offset]); |
| 442 |
| 443 listHeader.entsize = [cursor readInt32]; |
| 444 listHeader.count = [cursor readInt32]; |
| 445 NSParameterAssert(listHeader.entsize == 24); |
| 446 |
| 447 for (index = 0; index < listHeader.count; index++) { |
| 448 struct cd_objc2_method_64 objc2Method; |
| 449 NSString *name, *types; |
| 450 CDOCMethod *method; |
| 451 |
| 452 objc2Method.name = [cursor readInt64]; |
| 453 objc2Method.types = [cursor readInt64]; |
| 454 objc2Method.imp = [cursor readInt64]; |
| 455 name = [machOFile stringAtAddress:objc2Method.name]; |
| 456 types = [machOFile stringAtAddress:objc2Method.types]; |
| 457 |
| 458 //NSLog(@"%3u: %016lx %016lx %016lx", index, objc2Method.name, objc2
Method.types, objc2Method.imp); |
| 459 //NSLog(@"name: %@", name); |
| 460 //NSLog(@"types: %@", types); |
| 461 |
| 462 method = [[CDOCMethod alloc] initWithName:name type:types imp:objc2M
ethod.imp]; |
| 463 [methods addObject:method]; |
| 464 [method release]; |
| 465 } |
| 466 |
| 467 [cursor release]; |
| 468 } |
| 469 |
| 470 return [methods reversedArray]; |
| 471 } |
| 472 |
| 473 - (NSArray *)loadIvarsAtAddress:(uint64_t)address; |
| 474 { |
| 475 NSMutableArray *ivars; |
| 476 |
| 477 ivars = [NSMutableArray array]; |
| 478 |
| 479 if (address != 0) { |
| 480 CDDataCursor *cursor; |
| 481 struct cd_objc2_list_header listHeader; |
| 482 uint32_t index; |
| 483 |
| 484 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 485 [cursor setByteOrder:[machOFile byteOrder]]; |
| 486 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 487 NSParameterAssert([cursor offset] != 0); |
| 488 //NSLog(@"ivar list data offset: %lu", [cursor offset]); |
| 489 |
| 490 listHeader.entsize = [cursor readInt32]; |
| 491 listHeader.count = [cursor readInt32]; |
| 492 NSParameterAssert(listHeader.entsize == 32); |
| 493 |
| 494 for (index = 0; index < listHeader.count; index++) { |
| 495 struct cd_objc2_ivar_64 objc2Ivar; |
| 496 CDOCIvar *ivar; |
| 497 |
| 498 objc2Ivar.offset = [cursor readInt64]; |
| 499 objc2Ivar.name = [cursor readInt64]; |
| 500 objc2Ivar.type = [cursor readInt64]; |
| 501 objc2Ivar.alignment = [cursor readInt32]; |
| 502 objc2Ivar.size = [cursor readInt32]; |
| 503 |
| 504 if (objc2Ivar.name != 0) { |
| 505 NSString *name, *type; |
| 506 |
| 507 name = [machOFile stringAtAddress:objc2Ivar.name]; |
| 508 type = [machOFile stringAtAddress:objc2Ivar.type]; |
| 509 |
| 510 ivar = [[CDOCIvar alloc] initWithName:name type:type offset:objc
2Ivar.offset]; |
| 511 [ivars addObject:ivar]; |
| 512 [ivar release]; |
| 513 } else { |
| 514 //NSLog(@"%016lx %016lx %016lx %08x %08x", objc2Ivar.offset, ob
jc2Ivar.name, objc2Ivar.type, objc2Ivar.alignment, objc2Ivar.size); |
| 515 } |
| 516 } |
| 517 |
| 518 [cursor release]; |
| 519 } |
| 520 |
| 521 return ivars; |
| 522 } |
| 523 |
| 524 // Returns list of uniqued protocols. |
| 525 - (NSArray *)uniquedProtocolListAtAddress:(uint64_t)address; |
| 526 { |
| 527 NSMutableArray *protocols; |
| 528 |
| 529 protocols = [[[NSMutableArray alloc] init] autorelease];; |
| 530 |
| 531 if (address != 0) { |
| 532 CDDataCursor *cursor; |
| 533 uint64_t count, index; |
| 534 |
| 535 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 536 [cursor setByteOrder:[machOFile byteOrder]]; |
| 537 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 538 |
| 539 count = [cursor readInt64]; |
| 540 for (index = 0; index < count; index++) { |
| 541 uint64_t val; |
| 542 CDOCProtocol *protocol, *uniqueProtocol; |
| 543 |
| 544 val = [cursor readInt64]; |
| 545 if (val == 0) { |
| 546 NSLog(@"Warning: protocol address in protocol list was 0."); |
| 547 } else { |
| 548 protocol = [protocolsByAddress objectForKey:[NSNumber numberWith
UnsignedInteger:val]]; |
| 549 if (protocol != nil) { |
| 550 uniqueProtocol = [protocolsByName objectForKey:[protocol nam
e]]; |
| 551 if (uniqueProtocol != nil) |
| 552 [protocols addObject:uniqueProtocol]; |
| 553 } |
| 554 } |
| 555 } |
| 556 |
| 557 [cursor release]; |
| 558 } |
| 559 |
| 560 return protocols; |
| 561 } |
| 562 |
| 563 @end |
OLD | NEW |