Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: class-dump/src/CDObjectiveC1Processor.m

Issue 7793008: Add the 3.3.3 sources for class-dump. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/
Patch Set: Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « class-dump/src/CDObjectiveC1Processor.h ('k') | class-dump/src/CDObjectiveC2Processor32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(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 "CDObjectiveC1Processor.h"
7
8 #include <mach-o/arch.h>
9
10 #import "CDClassDump.h"
11 #import "CDLCDylib.h"
12 #import "CDMachOFile.h"
13 #import "CDOCCategory.h"
14 #import "CDOCClass.h"
15 #import "CDOCIvar.h"
16 #import "CDOCMethod.h"
17 #import "CDOCModule.h"
18 #import "CDOCProtocol.h"
19 #import "CDOCSymtab.h"
20 #import "CDSection32.h"
21 #import "CDLCSegment32.h"
22 #import "NSArray-Extensions.h"
23 #import "CDVisitor.h"
24
25
26 #import "CDSection.h"
27 #import "CDLCSegment.h"
28
29 // Section: __module_info
30 struct cd_objc_module {
31 uint32_t version;
32 uint32_t size;
33 uint32_t name;
34 uint32_t symtab;
35 };
36
37 // Section: __symbols
38 struct cd_objc_symtab
39 {
40 uint32_t sel_ref_cnt;
41 uint32_t refs; // not used until runtime?
42 uint16_t cls_def_count;
43 uint16_t cat_def_count;
44 //long class_pointer;
45 };
46
47 // Section: __class
48 struct cd_objc_class
49 {
50 uint32_t isa;
51 uint32_t super_class;
52 uint32_t name;
53 uint32_t version;
54 uint32_t info;
55 uint32_t instance_size;
56 uint32_t ivars;
57 uint32_t methods;
58 uint32_t cache;
59 uint32_t protocols;
60 };
61
62 // Section: ??
63 struct cd_objc_category
64 {
65 uint32_t category_name;
66 uint32_t class_name;
67 uint32_t methods;
68 uint32_t class_methods;
69 uint32_t protocols;
70 };
71
72 // Section: __instance_vars
73 struct cd_objc_ivar_list
74 {
75 uint32_t ivar_count;
76 // Followed by ivars
77 };
78
79 // Section: __instance_vars
80 struct cd_objc_ivar
81 {
82 uint32_t name;
83 uint32_t type;
84 uint32_t offset;
85 };
86
87 // Section: __inst_meth
88 struct cd_objc_method_list
89 {
90 uint32_t _obsolete;
91 uint32_t method_count;
92 // Followed by methods
93 };
94
95 // Section: __inst_meth
96 struct cd_objc_method
97 {
98 uint32_t name;
99 uint32_t types;
100 uint32_t imp;
101 };
102
103
104 struct cd_objc_protocol_list
105 {
106 uint32_t next;
107 uint32_t count;
108 //uint32_t list;
109 };
110
111 struct cd_objc_protocol
112 {
113 uint32_t isa;
114 uint32_t protocol_name;
115 uint32_t protocol_list;
116 uint32_t instance_methods;
117 uint32_t class_methods;
118 };
119
120 struct cd_objc_protocol_method_list
121 {
122 uint32_t method_count;
123 // Followed by methods
124 };
125
126 struct cd_objc_protocol_method
127 {
128 uint32_t name;
129 uint32_t types;
130 };
131
132 static BOOL debug = NO;
133
134 @implementation CDObjectiveC1Processor
135
136 - (id)initWithMachOFile:(CDMachOFile *)aMachOFile;
137 {
138 if ([super initWithMachOFile:aMachOFile] == nil)
139 return nil;
140
141 modules = [[NSMutableArray alloc] init];
142
143 return self;
144 }
145
146 - (void)dealloc;
147 {
148 [modules release];
149
150 [super dealloc];
151 }
152
153 - (void)process;
154 {
155 if ([machOFile isEncrypted] == NO && [machOFile canDecryptAllSegments]) {
156 [super process];
157
158 [self processModules];
159 }
160 }
161
162 //
163 // Formerly private
164 //
165
166 - (void)processModules;
167 {
168 CDLCSegment *objcSegment;
169 CDSection *moduleSection;
170 NSData *sectionData;
171 CDDataCursor *cursor;
172
173 objcSegment = [machOFile segmentWithName:@"__OBJC"];
174 moduleSection = [objcSegment sectionWithName:@"__module_info"];
175 sectionData = [moduleSection data];
176
177 cursor = [[CDDataCursor alloc] initWithData:sectionData];
178 [cursor setByteOrder:[machOFile byteOrder]];
179 while ([cursor isAtEnd] == NO) {
180 struct cd_objc_module objcModule;
181 CDOCModule *module;
182 NSString *name;
183 NSArray *array;
184
185 objcModule.version = [cursor readInt32];
186 objcModule.size = [cursor readInt32];
187 objcModule.name = [cursor readInt32];
188 objcModule.symtab = [cursor readInt32];
189
190 //NSLog(@"objcModule.size: %u", objcModule.size);
191 //NSLog(@"sizeof(struct cd_objc_module): %u", sizeof(struct cd_objc_modu le));
192 assert(objcModule.size == sizeof(struct cd_objc_module)); // Because thi s is what we're assuming.
193
194 name = [machOFile stringAtAddress:objcModule.name];
195 if (name != nil && [name length] > 0 && debug)
196 NSLog(@"Note: a module name is set: %@", name);
197
198 //NSLog(@"%08x %08x %08x %08x - '%@'", objcModule.version, objcModule.si ze, objcModule.name, objcModule.symtab, name);
199 //NSLog(@"\tsect: %@", [[machOFile segmentContainingAddress:objcModule.n ame] sectionContainingAddress:objcModule.name]);
200 //NSLog(@"symtab: %08x", objcModule.symtab);
201
202 module = [[CDOCModule alloc] init];
203 [module setVersion:objcModule.version];
204 [module setName:[machOFile stringAtAddress:objcModule.name]];
205 [module setSymtab:[self processSymtabAtAddress:objcModule.symtab]];
206 [modules addObject:module];
207
208 array = [[module symtab] classes];
209 if (array != nil)
210 [classes addObjectsFromArray:array];
211
212 array = [[module symtab] categories];
213 if (array != nil)
214 [categories addObjectsFromArray:array];
215
216 [module release];
217 }
218
219 [cursor release];
220 }
221
222 - (CDOCSymtab *)processSymtabAtAddress:(uint32_t)address;
223 {
224 CDDataCursor *cursor;
225 struct cd_objc_symtab objcSymtab;
226 CDOCSymtab *aSymtab = nil;
227 unsigned int index;
228
229 //----------------------------------------
230
231 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]];
232 [cursor setByteOrder:[machOFile byteOrder]];
233 [cursor setOffset:[machOFile dataOffsetForAddress:address segmentName:@"__OB JC"]];
234 //[cursor setOffset:[machOFile dataOffsetForAddress:address]];
235 //NSLog(@"cursor offset: %08x", [cursor offset]);
236 if ([cursor offset] != 0) {
237 objcSymtab.sel_ref_cnt = [cursor readInt32];
238 objcSymtab.refs = [cursor readInt32];
239 objcSymtab.cls_def_count = [cursor readInt16];
240 objcSymtab.cat_def_count = [cursor readInt16];
241 //NSLog(@"[@ %08x]: %08x %08x %04x %04x", address, objcSymtab.sel_ref_cn t, objcSymtab.refs, objcSymtab.cls_def_count, objcSymtab.cat_def_count);
242
243 aSymtab = [[[CDOCSymtab alloc] init] autorelease];
244
245 for (index = 0; index < objcSymtab.cls_def_count; index++) {
246 CDOCClass *aClass;
247 uint32_t val;
248
249 val = [cursor readInt32];
250 //NSLog(@"%4d: %08x", index, val);
251
252 aClass = [self processClassDefinitionAtAddress:val];
253 if (aClass != nil)
254 [aSymtab addClass:aClass];
255 }
256
257 for (index = 0; index < objcSymtab.cat_def_count; index++) {
258 CDOCCategory *aCategory;
259 uint32_t val;
260
261 val = [cursor readInt32];
262 //NSLog(@"%4d: %08x", index, val);
263
264 aCategory = [self processCategoryDefinitionAtAddress:val];
265 if (aCategory != nil)
266 [aSymtab addCategory:aCategory];
267 }
268 }
269
270 [cursor release];
271
272 return aSymtab;
273 }
274
275 - (CDOCClass *)processClassDefinitionAtAddress:(uint32_t)address;
276 {
277 CDDataCursor *cursor;
278 struct cd_objc_class objcClass;
279 CDOCClass *aClass;
280 NSString *name;
281
282 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]];
283 [cursor setByteOrder:[machOFile byteOrder]];
284 [cursor setOffset:[machOFile dataOffsetForAddress:address]];
285
286 objcClass.isa = [cursor readInt32];
287 objcClass.super_class = [cursor readInt32];
288 objcClass.name = [cursor readInt32];
289 objcClass.version = [cursor readInt32];
290 objcClass.info = [cursor readInt32];
291 objcClass.instance_size = [cursor readInt32];
292 objcClass.ivars = [cursor readInt32];
293 objcClass.methods = [cursor readInt32];
294 objcClass.cache = [cursor readInt32];
295 objcClass.protocols = [cursor readInt32];
296
297 name = [machOFile stringAtAddress:objcClass.name];
298 //NSLog(@"name: %08x", objcClass.name);
299 //NSLog(@"name = %@", name);
300 if (name == nil) {
301 NSLog(@"Note: objcClass.name was %08x, returning nil.", objcClass.name);
302 [cursor release];
303 return nil;
304 }
305
306 aClass = [[[CDOCClass alloc] init] autorelease];
307 [aClass setName:name];
308 [aClass setSuperClassName:[machOFile stringAtAddress:objcClass.super_class]] ;
309 //NSLog(@"[aClass superClassName]: %@", [aClass superClassName]);
310
311 // Process ivars
312 if (objcClass.ivars != 0) {
313 uint32_t count, index;
314 NSMutableArray *ivars;
315
316 [cursor setOffset:[machOFile dataOffsetForAddress:objcClass.ivars]];
317 NSParameterAssert([cursor offset] != 0);
318
319 count = [cursor readInt32];
320 ivars = [[NSMutableArray alloc] init];
321 for (index = 0; index < count; index++) {
322 struct cd_objc_ivar objcIvar;
323 NSString *name, *type;
324
325 objcIvar.name = [cursor readInt32];
326 objcIvar.type = [cursor readInt32];
327 objcIvar.offset = [cursor readInt32];
328
329 name = [machOFile stringAtAddress:objcIvar.name];
330 type = [machOFile stringAtAddress:objcIvar.type];
331
332 // bitfields don't need names.
333 // NSIconRefBitmapImageRep in AppKit on 10.5 has a single-bit bitfie ld, plus an unnamed 31-bit field.
334 if (type != nil) {
335 CDOCIvar *anIvar;
336
337 anIvar = [[CDOCIvar alloc] initWithName:name type:type offset:ob jcIvar.offset];
338 [ivars addObject:anIvar];
339 [anIvar release];
340 }
341 }
342
343 [aClass setIvars:[NSArray arrayWithArray:ivars]];
344 [ivars release];
345 }
346
347 // Process instance methods
348 for (CDOCMethod *method in [self processMethodsAtAddress:objcClass.methods])
349 [aClass addInstanceMethod:method];
350
351 // Process meta class
352 {
353 struct cd_objc_class metaClass;
354
355 NSParameterAssert(objcClass.isa != 0);
356 //NSLog(@"meta class, isa = %08x", objcClass.isa);
357
358 [cursor setOffset:[machOFile dataOffsetForAddress:objcClass.isa]];
359
360 metaClass.isa = [cursor readInt32];
361 metaClass.super_class = [cursor readInt32];
362 metaClass.name = [cursor readInt32];
363 metaClass.version = [cursor readInt32];
364 metaClass.info = [cursor readInt32];
365 metaClass.instance_size = [cursor readInt32];
366 metaClass.ivars = [cursor readInt32];
367 metaClass.methods = [cursor readInt32];
368 metaClass.cache = [cursor readInt32];
369 metaClass.protocols = [cursor readInt32];
370
371 #if 0
372 // TODO (2009-06-23): See if there's anything else interesting here.
373 NSLog(@"metaclass= isa:%08x super:%08x name:%08x ver:%08x info:%08x is ize:%08x ivar:%08x meth:%08x cache:%08x proto:%08x",
374 metaClass.isa, metaClass.super_class, metaClass.name, metaClass.ve rsion, metaClass.info, metaClass.instance_size,
375 metaClass.ivars, metaClass.methods, metaClass.cache, metaClass.pro tocols);
376 #endif
377 // Process class methods
378 for (CDOCMethod *method in [self processMethodsAtAddress:metaClass.metho ds])
379 [aClass addClassMethod:method];
380 }
381
382 // Process protocols
383 for (CDOCProtocol *protocol in [self uniquedProtocolListAtAddress:objcClass. protocols])
384 [aClass addProtocol:protocol];
385
386 [cursor release];
387
388 return aClass;
389 }
390
391 // Returns list of uniqued protocols.
392 - (NSArray *)uniquedProtocolListAtAddress:(uint32_t)address;
393 {
394 NSMutableArray *protocols;
395
396 protocols = [[[NSMutableArray alloc] init] autorelease];;
397
398 if (address != 0) {
399 CDDataCursor *cursor;
400 struct cd_objc_protocol_list protocolList;
401 uint32_t index;
402
403 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]];
404 [cursor setByteOrder:[machOFile byteOrder]];
405 [cursor setOffset:[machOFile dataOffsetForAddress:address]];
406
407 protocolList.next = [cursor readInt32];
408 protocolList.count = [cursor readInt32];
409
410 for (index = 0; index < protocolList.count; index++) {
411 uint32_t val;
412 CDOCProtocol *protocol, *uniqueProtocol;
413
414 val = [cursor readInt32];
415 protocol = [protocolsByAddress objectForKey:[NSNumber numberWithUnsi gnedInt:val]];
416 //NSLog(@"%3d protocol @ %08x: %@", index, val, [protocol name]);
417 if (protocol != nil) {
418 uniqueProtocol = [protocolsByName objectForKey:[protocol name]];
419 if (uniqueProtocol != nil)
420 [protocols addObject:uniqueProtocol];
421 }
422 }
423
424 [cursor release];
425 }
426
427 return protocols;
428 }
429
430 - (NSArray *)processMethodsAtAddress:(uint32_t)address;
431 {
432 return [self processMethodsAtAddress:address isFromProtocolDefinition:NO];
433 }
434
435 - (NSArray *)processMethodsAtAddress:(uint32_t)address isFromProtocolDefinition: (BOOL)isFromProtocolDefinition;
436 {
437 CDDataCursor *cursor;
438 NSMutableArray *methods;
439
440 if (address == 0)
441 return [NSArray array];
442
443 methods = [NSMutableArray array];
444
445 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]];
446 [cursor setByteOrder:[machOFile byteOrder]];
447 [cursor setOffset:[machOFile dataOffsetForAddress:address]];
448 if ([cursor offset] != 0) {
449 struct cd_objc_method_list methodList;
450 uint32_t index;
451
452 if (isFromProtocolDefinition)
453 methodList._obsolete = 0;
454 else
455 methodList._obsolete = [cursor readInt32];
456 methodList.method_count = [cursor readInt32];
457
458 for (index = 0; index < methodList.method_count; index++) {
459 struct cd_objc_method objcMethod;
460 NSString *name, *type;
461
462 objcMethod.name = [cursor readInt32];
463 objcMethod.types = [cursor readInt32];
464 if (isFromProtocolDefinition)
465 objcMethod.imp = 0;
466 else
467 objcMethod.imp = [cursor readInt32];
468
469 name = [machOFile stringAtAddress:objcMethod.name];
470 type = [machOFile stringAtAddress:objcMethod.types];
471 if (name != nil && type != nil) {
472 CDOCMethod *method;
473
474 method = [[CDOCMethod alloc] initWithName:name type:type imp:obj cMethod.imp];
475 [methods addObject:method];
476 [method release];
477 } else {
478 if (name == nil) NSLog(@"Note: Method name was nil (%08x, %p)", objcMethod.name, name);
479 if (type == nil) NSLog(@"Note: Method type was nil (%08x, %p)", objcMethod.types, type);
480 }
481 }
482 }
483
484 [cursor release];
485
486 return [methods reversedArray];
487 }
488
489 - (CDOCCategory *)processCategoryDefinitionAtAddress:(uint32_t)address;
490 {
491 CDOCCategory *aCategory = nil;
492
493 if (address != 0) {
494 CDDataCursor *cursor;
495 struct cd_objc_category objcCategory;
496 NSString *name;
497
498 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]];
499 [cursor setByteOrder:[machOFile byteOrder]];
500 [cursor setOffset:[machOFile dataOffsetForAddress:address]];
501
502 objcCategory.category_name = [cursor readInt32];
503 objcCategory.class_name = [cursor readInt32];
504 objcCategory.methods = [cursor readInt32];
505 objcCategory.class_methods = [cursor readInt32];
506 objcCategory.protocols = [cursor readInt32];
507
508 name = [machOFile stringAtAddress:objcCategory.category_name];
509 if (name == nil) {
510 NSLog(@"Note: objcCategory.category_name was %08x, returning nil.", objcCategory.category_name);
511 [cursor release];
512 return nil;
513 }
514
515 aCategory = [[[CDOCCategory alloc] init] autorelease];
516 [aCategory setName:name];
517 [aCategory setClassName:[machOFile stringAtAddress:objcCategory.class_na me]];
518
519 for (CDOCMethod *method in [self processMethodsAtAddress:objcCategory.me thods])
520 [aCategory addInstanceMethod:method];
521
522 for (CDOCMethod *method in [self processMethodsAtAddress:objcCategory.cl ass_methods])
523 [aCategory addClassMethod:method];
524
525 for (CDOCProtocol *protocol in [self uniquedProtocolListAtAddress:objcCa tegory.protocols])
526 [aCategory addProtocol:protocol];
527
528 [cursor release];
529 }
530
531 return aCategory;
532 }
533
534 - (CDOCProtocol *)protocolAtAddress:(uint32_t)address;
535 {
536 NSNumber *key;
537 CDOCProtocol *aProtocol;
538
539 key = [NSNumber numberWithUnsignedInt:address];
540 aProtocol = [protocolsByAddress objectForKey:key];
541 if (aProtocol == nil) {
542 CDDataCursor *cursor;
543 uint32_t v1, v2, v3, v4, v5;
544 NSString *name;
545
546 //NSLog(@"Creating new protocol from address: 0x%08x", address);
547 aProtocol = [[[CDOCProtocol alloc] init] autorelease];
548 [protocolsByAddress setObject:aProtocol forKey:key];
549
550 cursor = [[CDDataCursor alloc] initWithData:[machOFile data]];
551 [cursor setByteOrder:[machOFile byteOrder]];
552 [cursor setOffset:[machOFile dataOffsetForAddress:address]];
553
554 v1 = [cursor readInt32];
555 v2 = [cursor readInt32];
556 v3 = [cursor readInt32];
557 v4 = [cursor readInt32];
558 v5 = [cursor readInt32];
559 name = [machOFile stringAtAddress:v2];
560 [aProtocol setName:name]; // Need to set name before adding to another p rotocol
561 //NSLog(@"data offset for %08x: %08x", v2, [machOFile dataOffsetForAddre ss:v2]);
562 //NSLog(@"[@ %08x] v1-5: 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x (%@)", addre ss, v1, v2, v3, v4, v5, name);
563
564 {
565 uint32_t count, index;
566
567 // Protocols
568 if (v3 != 0) {
569 uint32_t val;
570
571 [cursor setOffset:[machOFile dataOffsetForAddress:v3]];
572 val = [cursor readInt32];
573 NSParameterAssert(val == 0); // next pointer, let me know if it' s ever not zero
574 //NSLog(@"val: 0x%08x", val);
575 count = [cursor readInt32];
576 //NSLog(@"protocol count: %08x", count);
577 for (index = 0; index < count; index++) {
578 CDOCProtocol *anotherProtocol;
579
580 val = [cursor readInt32];
581 //NSLog(@"val[%2d]: 0x%08x", index, val);
582 anotherProtocol = [self protocolAtAddress:val];
583 if (anotherProtocol != nil) {
584 [aProtocol addProtocol:anotherProtocol];
585 } else {
586 NSLog(@"Note: another protocol was nil.");
587 }
588 }
589 }
590
591 // Instance methods
592 for (CDOCMethod *method in [self processMethodsAtAddress:v4 isFromPr otocolDefinition:YES])
593 [aProtocol addInstanceMethod:method];
594
595 // Class methods
596 for (CDOCMethod *method in [self processMethodsAtAddress:v5 isFromPr otocolDefinition:YES])
597 [aProtocol addClassMethod:method];
598 }
599
600 [cursor release];
601 } else {
602 //NSLog(@"Found existing protocol at address: 0x%08x", address);
603 }
604
605 return aProtocol;
606 }
607
608 // Protocols can reference other protocols, so we can't try to create them
609 // in order. Instead we create them lazily and just make sure we reference
610 // all available protocols.
611
612 // Many of the protocol structures share the same name, but have differnt method lists. Create them all, then merge/unique by name after.
613 // Perhaps a bit more work than necessary, but at least I can see exactly what i s happening.
614 - (void)loadProtocols;
615 {
616 CDLCSegment *objcSegment;
617 CDSection *protocolSection;
618 uint32_t addr;
619 int count, index;
620
621 objcSegment = [machOFile segmentWithName:@"__OBJC"];
622 protocolSection = [objcSegment sectionWithName:@"__protocol"];
623 addr = [protocolSection addr];
624
625 count = [protocolSection size] / sizeof(struct cd_objc_protocol);
626 for (index = 0; index < count; index++, addr += sizeof(struct cd_objc_protoc ol))
627 [self protocolAtAddress:addr]; // Forces them to be loaded
628
629 [self createUniquedProtocols];
630 }
631
632 - (NSData *)objcImageInfoData;
633 {
634 return [[[machOFile segmentWithName:@"__OBJC"] sectionWithName:@"__image_inf o"] data];
635 }
636
637 @end
OLDNEW
« no previous file with comments | « class-dump/src/CDObjectiveC1Processor.h ('k') | class-dump/src/CDObjectiveC2Processor32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698