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 "CDObjectiveC2Processor32.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 CDObjectiveC2Processor32 |
| 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 readInt32]]; |
| 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 uint32_t val; |
| 60 CDOCClass *aClass; |
| 61 |
| 62 val = [cursor readInt32]; |
| 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 readInt32]]; |
| 90 if (category != nil) |
| 91 [categories addObject:category]; |
| 92 } |
| 93 |
| 94 [cursor release]; |
| 95 } |
| 96 |
| 97 - (CDOCProtocol *)protocolAtAddress:(uint32_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_32 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 readInt32]; |
| 121 objc2Protocol.name = [cursor readInt32]; |
| 122 objc2Protocol.protocols = [cursor readInt32]; |
| 123 objc2Protocol.instanceMethods = [cursor readInt32]; |
| 124 objc2Protocol.classMethods = [cursor readInt32]; |
| 125 objc2Protocol.optionalInstanceMethods = [cursor readInt32]; |
| 126 objc2Protocol.optionalClassMethods = [cursor readInt32]; |
| 127 objc2Protocol.instanceProperties = [cursor readInt32]; |
| 128 |
| 129 //NSLog(@"----------------------------------------"); |
| 130 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Protocol.isa, objc2Protocol.nam
e, objc2Protocol.protocols, objc2Protocol.instanceMethods); |
| 131 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Protocol.classMethods, objc2Pro
tocol.optionalInstanceMethods, objc2Protocol.optionalClassMethods, objc2Protocol
.instanceProperties); |
| 132 |
| 133 str = [machOFile stringAtAddress:objc2Protocol.name]; |
| 134 [protocol setName:str]; |
| 135 |
| 136 if (objc2Protocol.protocols != 0) { |
| 137 uint32_t count, index; |
| 138 |
| 139 [cursor setOffset:[machOFile dataOffsetForAddress:objc2Protocol.prot
ocols]]; |
| 140 count = [cursor readInt32]; |
| 141 for (index = 0; index < count; index++) { |
| 142 uint32_t val; |
| 143 CDOCProtocol *anotherProtocol; |
| 144 |
| 145 val = [cursor readInt32]; |
| 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:(uint32_t)address; |
| 177 { |
| 178 struct cd_objc2_category_32 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 readInt32]; |
| 192 objc2Category.class = [cursor readInt32]; |
| 193 objc2Category.instanceMethods = [cursor readInt32]; |
| 194 objc2Category.classMethods = [cursor readInt32]; |
| 195 objc2Category.protocols = [cursor readInt32]; |
| 196 objc2Category.instanceProperties = [cursor readInt32]; |
| 197 objc2Category.v7 = [cursor readInt32]; |
| 198 objc2Category.v8 = [cursor readInt32]; |
| 199 //NSLog(@"----------------------------------------"); |
| 200 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Category.name, objc2Category.class,
objc2Category.instanceMethods, objc2Category.classMethods); |
| 201 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Category.protocols, objc2Category.i
nstanceProperties, 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:(uint32_t)address; |
| 242 { |
| 243 struct cd_objc2_class_32 objc2Class; |
| 244 struct cd_objc2_class_ro_t_32 objc2ClassData; |
| 245 CDDataCursor *cursor; |
| 246 NSString *str; |
| 247 CDOCClass *aClass; |
| 248 |
| 249 if (address == 0) |
| 250 return nil; |
| 251 |
| 252 //NSLog(@"%s, address=%08lx", _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 readInt32]; |
| 260 objc2Class.superclass = [cursor readInt32]; |
| 261 objc2Class.cache = [cursor readInt32]; |
| 262 objc2Class.vtable = [cursor readInt32]; |
| 263 objc2Class.data = [cursor readInt32]; |
| 264 objc2Class.reserved1 = [cursor readInt32]; |
| 265 objc2Class.reserved2 = [cursor readInt32]; |
| 266 objc2Class.reserved3 = [cursor readInt32]; |
| 267 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Class.isa, objc2Class.superclass, o
bjc2Class.cache, objc2Class.vtable); |
| 268 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Class.data, objc2Class.reserved1, o
bjc2Class.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 objc2ClassData.reserved = 0; |
| 277 |
| 278 objc2ClassData.ivarLayout = [cursor readInt32]; |
| 279 objc2ClassData.name = [cursor readInt32]; |
| 280 objc2ClassData.baseMethods = [cursor readInt32]; |
| 281 objc2ClassData.baseProtocols = [cursor readInt32]; |
| 282 objc2ClassData.ivars = [cursor readInt32]; |
| 283 objc2ClassData.weakIvarLayout = [cursor readInt32]; |
| 284 objc2ClassData.baseProperties = [cursor readInt32]; |
| 285 |
| 286 //NSLog(@"%08x %08x %08x %08x", objc2ClassData.flags, objc2ClassData.instanc
eStart, objc2ClassData.instanceSize, objc2ClassData.reserved); |
| 287 |
| 288 //NSLog(@"%08lx %08lx %08lx %08lx", objc2ClassData.ivarLayout, objc2ClassDat
a.name, objc2ClassData.baseMethods, objc2ClassData.baseProtocols); |
| 289 //NSLog(@"%08lx %08lx %08lx %08lx", objc2ClassData.ivars, objc2ClassData.wea
kIvarLayout, objc2ClassData.baseProperties); |
| 290 str = [machOFile stringAtAddress:objc2ClassData.name]; |
| 291 //NSLog(@"name = %@", str); |
| 292 |
| 293 aClass = [[[CDOCClass alloc] init] autorelease]; |
| 294 [aClass setName:str]; |
| 295 |
| 296 for (CDOCMethod *method in [self loadMethodsAtAddress:objc2ClassData.baseMet
hods]) |
| 297 [aClass addInstanceMethod:method]; |
| 298 |
| 299 [aClass setIvars:[self loadIvarsAtAddress:objc2ClassData.ivars]]; |
| 300 |
| 301 [cursor release]; |
| 302 |
| 303 { |
| 304 uint64_t classNameAddress = address + sizeof(objc2Class.isa); |
| 305 |
| 306 if ([machOFile hasRelocationEntryForAddress2:classNameAddress]) { |
| 307 [aClass setSuperClassName:[machOFile externalClassNameForAddress2:cl
assNameAddress]]; |
| 308 //NSLog(@"class: got external class name (2): %@", [aClass superClas
sName]); |
| 309 } else if ([machOFile hasRelocationEntryForAddress:classNameAddress]) { |
| 310 [aClass setSuperClassName:[machOFile externalClassNameForAddress:cla
ssNameAddress]]; |
| 311 //NSLog(@"class: got external class name (1): %@", [aClass superClas
sName]); |
| 312 } else if (objc2Class.superclass != 0) { |
| 313 CDOCClass *sc; |
| 314 |
| 315 sc = [self loadClassAtAddress:objc2Class.superclass]; |
| 316 [aClass setSuperClassName:[sc name]]; |
| 317 } |
| 318 } |
| 319 |
| 320 for (CDOCMethod *method in [self loadMethodsOfMetaClassAtAddress:objc2Class.
isa]) |
| 321 [aClass addClassMethod:method]; |
| 322 |
| 323 // Process protocols |
| 324 for (CDOCProtocol *protocol in [self uniquedProtocolListAtAddress:objc2Class
Data.baseProtocols]) |
| 325 [aClass addProtocol:protocol]; |
| 326 |
| 327 for (CDOCProperty *property in [self loadPropertiesAtAddress:objc2ClassData.
baseProperties]) |
| 328 [aClass addProperty:property]; |
| 329 |
| 330 return aClass; |
| 331 } |
| 332 |
| 333 - (NSArray *)loadPropertiesAtAddress:(uint32_t)address; |
| 334 { |
| 335 NSMutableArray *properties; |
| 336 |
| 337 properties = [NSMutableArray array]; |
| 338 if (address != 0) { |
| 339 CDDataCursor *cursor; |
| 340 struct cd_objc2_list_header listHeader; |
| 341 uint32_t index; |
| 342 |
| 343 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 344 [cursor setByteOrder:[machOFile byteOrder]]; |
| 345 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 346 NSParameterAssert([cursor offset] != 0); |
| 347 //NSLog(@"property list data offset: %lu", [cursor offset]); |
| 348 |
| 349 listHeader.entsize = [cursor readInt32]; |
| 350 listHeader.count = [cursor readInt32]; |
| 351 NSParameterAssert(listHeader.entsize == 8); |
| 352 |
| 353 for (index = 0; index < listHeader.count; index++) { |
| 354 struct cd_objc2_property_32 objc2Property; |
| 355 NSString *name, *attributes; |
| 356 CDOCProperty *property; |
| 357 |
| 358 objc2Property.name = [cursor readInt32]; |
| 359 objc2Property.attributes = [cursor readInt32]; |
| 360 name = [machOFile stringAtAddress:objc2Property.name]; |
| 361 attributes = [machOFile stringAtAddress:objc2Property.attributes]; |
| 362 |
| 363 property = [[CDOCProperty alloc] initWithName:name attributes:attrib
utes]; |
| 364 [properties addObject:property]; |
| 365 [property release]; |
| 366 } |
| 367 |
| 368 [cursor release]; |
| 369 } |
| 370 |
| 371 return properties; |
| 372 } |
| 373 |
| 374 // This just gets the methods. |
| 375 - (NSArray *)loadMethodsOfMetaClassAtAddress:(uint32_t)address; |
| 376 { |
| 377 struct cd_objc2_class_32 objc2Class; |
| 378 struct cd_objc2_class_ro_t_32 objc2ClassData; |
| 379 CDDataCursor *cursor; |
| 380 |
| 381 if (address == 0) |
| 382 return nil; |
| 383 |
| 384 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 385 [cursor setByteOrder:[machOFile byteOrder]]; |
| 386 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 387 NSParameterAssert([cursor offset] != 0); |
| 388 |
| 389 objc2Class.isa = [cursor readInt32]; |
| 390 objc2Class.superclass = [cursor readInt32]; |
| 391 objc2Class.cache = [cursor readInt32]; |
| 392 objc2Class.vtable = [cursor readInt32]; |
| 393 objc2Class.data = [cursor readInt32]; |
| 394 objc2Class.reserved1 = [cursor readInt32]; |
| 395 objc2Class.reserved2 = [cursor readInt32]; |
| 396 objc2Class.reserved3 = [cursor readInt32]; |
| 397 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Class.isa, objc2Class.superclass, o
bjc2Class.cache, objc2Class.vtable); |
| 398 //NSLog(@"%08lx %08lx %08lx %08lx", objc2Class.data, objc2Class.reserved1, o
bjc2Class.reserved2, objc2Class.reserved3); |
| 399 |
| 400 NSParameterAssert(objc2Class.data != 0); |
| 401 [cursor setOffset:[machOFile dataOffsetForAddress:objc2Class.data]]; |
| 402 objc2ClassData.flags = [cursor readInt32]; |
| 403 objc2ClassData.instanceStart = [cursor readInt32]; |
| 404 objc2ClassData.instanceSize = [cursor readInt32]; |
| 405 //objc2ClassData.reserved = [cursor readInt32]; |
| 406 objc2ClassData.reserved = 0; |
| 407 |
| 408 objc2ClassData.ivarLayout = [cursor readInt32]; |
| 409 objc2ClassData.name = [cursor readInt32]; |
| 410 objc2ClassData.baseMethods = [cursor readInt32]; |
| 411 objc2ClassData.baseProtocols = [cursor readInt32]; |
| 412 objc2ClassData.ivars = [cursor readInt32]; |
| 413 objc2ClassData.weakIvarLayout = [cursor readInt32]; |
| 414 objc2ClassData.baseProperties = [cursor readInt32]; |
| 415 |
| 416 [cursor release]; |
| 417 |
| 418 return [self loadMethodsAtAddress:objc2ClassData.baseMethods]; |
| 419 } |
| 420 |
| 421 - (NSArray *)loadMethodsAtAddress:(uint32_t)address; |
| 422 { |
| 423 NSMutableArray *methods; |
| 424 |
| 425 methods = [NSMutableArray array]; |
| 426 |
| 427 if (address != 0) { |
| 428 CDDataCursor *cursor; |
| 429 struct cd_objc2_list_header listHeader; |
| 430 uint32_t index; |
| 431 |
| 432 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 433 [cursor setByteOrder:[machOFile byteOrder]]; |
| 434 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 435 NSParameterAssert([cursor offset] != 0); |
| 436 //NSLog(@"method list data offset: %lu", [cursor offset]); |
| 437 |
| 438 listHeader.entsize = [cursor readInt32]; |
| 439 listHeader.count = [cursor readInt32]; |
| 440 NSParameterAssert(listHeader.entsize == 12); |
| 441 |
| 442 for (index = 0; index < listHeader.count; index++) { |
| 443 struct cd_objc2_method_32 objc2Method; |
| 444 NSString *name, *types; |
| 445 CDOCMethod *method; |
| 446 |
| 447 objc2Method.name = [cursor readInt32]; |
| 448 objc2Method.types = [cursor readInt32]; |
| 449 objc2Method.imp = [cursor readInt32]; |
| 450 name = [machOFile stringAtAddress:objc2Method.name]; |
| 451 types = [machOFile stringAtAddress:objc2Method.types]; |
| 452 |
| 453 //NSLog(@"%3u: %08lx %08lx %08lx", index, objc2Method.name, objc2Met
hod.types, objc2Method.imp); |
| 454 //NSLog(@"name: %@", name); |
| 455 //NSLog(@"types: %@", types); |
| 456 |
| 457 method = [[CDOCMethod alloc] initWithName:name type:types imp:objc2M
ethod.imp]; |
| 458 [methods addObject:method]; |
| 459 [method release]; |
| 460 } |
| 461 |
| 462 [cursor release]; |
| 463 } |
| 464 |
| 465 return [methods reversedArray]; |
| 466 } |
| 467 |
| 468 - (NSArray *)loadIvarsAtAddress:(uint32_t)address; |
| 469 { |
| 470 NSMutableArray *ivars; |
| 471 |
| 472 ivars = [NSMutableArray array]; |
| 473 |
| 474 if (address != 0) { |
| 475 CDDataCursor *cursor; |
| 476 struct cd_objc2_list_header listHeader; |
| 477 uint32_t index; |
| 478 |
| 479 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 480 [cursor setByteOrder:[machOFile byteOrder]]; |
| 481 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 482 NSParameterAssert([cursor offset] != 0); |
| 483 //NSLog(@"ivar list data offset: %lu", [cursor offset]); |
| 484 |
| 485 listHeader.entsize = [cursor readInt32]; |
| 486 listHeader.count = [cursor readInt32]; |
| 487 NSParameterAssert(listHeader.entsize == 20); |
| 488 |
| 489 for (index = 0; index < listHeader.count; index++) { |
| 490 struct cd_objc2_ivar_32 objc2Ivar; |
| 491 CDOCIvar *ivar; |
| 492 |
| 493 objc2Ivar.offset = [cursor readInt32]; |
| 494 objc2Ivar.name = [cursor readInt32]; |
| 495 objc2Ivar.type = [cursor readInt32]; |
| 496 objc2Ivar.alignment = [cursor readInt32]; |
| 497 objc2Ivar.size = [cursor readInt32]; |
| 498 |
| 499 if (objc2Ivar.name != 0) { |
| 500 NSString *name, *type; |
| 501 |
| 502 name = [machOFile stringAtAddress:objc2Ivar.name]; |
| 503 type = [machOFile stringAtAddress:objc2Ivar.type]; |
| 504 |
| 505 ivar = [[CDOCIvar alloc] initWithName:name type:type offset:objc
2Ivar.offset]; |
| 506 [ivars addObject:ivar]; |
| 507 [ivar release]; |
| 508 } else { |
| 509 //NSLog(@"%08lx %08lx %08lx %08x %08x", objc2Ivar.offset, objc2
Ivar.name, objc2Ivar.type, objc2Ivar.alignment, objc2Ivar.size); |
| 510 } |
| 511 } |
| 512 |
| 513 [cursor release]; |
| 514 } |
| 515 |
| 516 return ivars; |
| 517 } |
| 518 |
| 519 // Returns list of uniqued protocols. |
| 520 - (NSArray *)uniquedProtocolListAtAddress:(uint32_t)address; |
| 521 { |
| 522 NSMutableArray *protocols; |
| 523 |
| 524 protocols = [[[NSMutableArray alloc] init] autorelease];; |
| 525 |
| 526 if (address != 0) { |
| 527 CDDataCursor *cursor; |
| 528 uint32_t count, index; |
| 529 |
| 530 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]]; |
| 531 [cursor setByteOrder:[machOFile byteOrder]]; |
| 532 [cursor setOffset:[machOFile dataOffsetForAddress:address]]; |
| 533 |
| 534 count = [cursor readInt32]; |
| 535 for (index = 0; index < count; index++) { |
| 536 uint32_t val; |
| 537 CDOCProtocol *protocol, *uniqueProtocol; |
| 538 |
| 539 val = [cursor readInt32]; |
| 540 if (val == 0) { |
| 541 NSLog(@"Warning: protocol address in protocol list was 0."); |
| 542 } else { |
| 543 protocol = [protocolsByAddress objectForKey:[NSNumber numberWith
UnsignedInteger:val]]; |
| 544 if (protocol != nil) { |
| 545 uniqueProtocol = [protocolsByName objectForKey:[protocol nam
e]]; |
| 546 if (uniqueProtocol != nil) |
| 547 [protocols addObject:uniqueProtocol]; |
| 548 } |
| 549 } |
| 550 } |
| 551 |
| 552 [cursor release]; |
| 553 } |
| 554 |
| 555 return protocols; |
| 556 } |
| 557 |
| 558 @end |
OLD | NEW |