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 "CDTypeController.h" |
| 7 |
| 8 #import "CDStructureTable.h" |
| 9 #import "CDClassDump.h" |
| 10 #import "CDTypeFormatter.h" |
| 11 #import "CDType.h" |
| 12 |
| 13 static BOOL debug = NO; |
| 14 |
| 15 @implementation CDTypeController |
| 16 |
| 17 - (id)initWithClassDump:(CDClassDump *)aClassDump; |
| 18 { |
| 19 if ([super init] == nil) |
| 20 return nil; |
| 21 |
| 22 ivarTypeFormatter = [[CDTypeFormatter alloc] init]; |
| 23 [ivarTypeFormatter setShouldExpand:NO]; |
| 24 [ivarTypeFormatter setShouldAutoExpand:YES]; |
| 25 [ivarTypeFormatter setBaseLevel:1]; |
| 26 [ivarTypeFormatter setTypeController:self]; |
| 27 |
| 28 methodTypeFormatter = [[CDTypeFormatter alloc] init]; |
| 29 [methodTypeFormatter setShouldExpand:NO]; |
| 30 [methodTypeFormatter setShouldAutoExpand:NO]; |
| 31 [methodTypeFormatter setBaseLevel:0]; |
| 32 [methodTypeFormatter setTypeController:self]; |
| 33 |
| 34 propertyTypeFormatter = [[CDTypeFormatter alloc] init]; |
| 35 [propertyTypeFormatter setShouldExpand:NO]; |
| 36 [propertyTypeFormatter setShouldAutoExpand:NO]; |
| 37 [propertyTypeFormatter setBaseLevel:0]; |
| 38 [propertyTypeFormatter setTypeController:self]; |
| 39 |
| 40 structDeclarationTypeFormatter = [[CDTypeFormatter alloc] init]; |
| 41 [structDeclarationTypeFormatter setShouldExpand:YES]; // But don't expand na
med struct members... |
| 42 [structDeclarationTypeFormatter setShouldAutoExpand:YES]; |
| 43 [structDeclarationTypeFormatter setBaseLevel:0]; |
| 44 [structDeclarationTypeFormatter setTypeController:self]; // But need to igno
re some things? |
| 45 |
| 46 structureTable = [[CDStructureTable alloc] init]; |
| 47 [structureTable setAnonymousBaseName:@"CDStruct_"]; |
| 48 [structureTable setIdentifier:@"Structs"]; |
| 49 |
| 50 unionTable = [[CDStructureTable alloc] init]; |
| 51 [unionTable setAnonymousBaseName:@"CDUnion_"]; |
| 52 [unionTable setIdentifier:@"Unions"]; |
| 53 |
| 54 nonretained_classDump = aClassDump; |
| 55 |
| 56 //[structureTable debugName:@"_xmlSAXHandler"]; |
| 57 //[structureTable debugName:@"UCKeyboardTypeHeader"]; |
| 58 //[structureTable debugName:@"UCKeyboardLayout"]; |
| 59 //[structureTable debugName:@"ppd_group_s"]; |
| 60 //[structureTable debugName:@"stat"]; |
| 61 //[structureTable debugName:@"timespec"]; |
| 62 //[structureTable debugName:@"AudioUnitEvent"]; |
| 63 //[structureTable debugAnon:@"{?=II}"]; |
| 64 //[structureTable debugName:@"_CommandStackEntry"]; |
| 65 //[structureTable debugName:@"_flags"]; |
| 66 |
| 67 return self; |
| 68 } |
| 69 |
| 70 - (void)dealloc; |
| 71 { |
| 72 [ivarTypeFormatter release]; |
| 73 [methodTypeFormatter release]; |
| 74 [propertyTypeFormatter release]; |
| 75 [structDeclarationTypeFormatter release]; |
| 76 |
| 77 [structureTable release]; |
| 78 [unionTable release]; |
| 79 |
| 80 [super dealloc]; |
| 81 } |
| 82 |
| 83 - (CDTypeFormatter *)ivarTypeFormatter; |
| 84 { |
| 85 return ivarTypeFormatter; |
| 86 } |
| 87 |
| 88 - (CDTypeFormatter *)methodTypeFormatter; |
| 89 { |
| 90 return methodTypeFormatter; |
| 91 } |
| 92 |
| 93 - (CDTypeFormatter *)propertyTypeFormatter; |
| 94 { |
| 95 return propertyTypeFormatter; |
| 96 } |
| 97 |
| 98 - (CDTypeFormatter *)structDeclarationTypeFormatter; |
| 99 { |
| 100 return structDeclarationTypeFormatter; |
| 101 } |
| 102 |
| 103 - (CDType *)typeFormatter:(CDTypeFormatter *)aFormatter replacementForType:(CDTy
pe *)aType; |
| 104 { |
| 105 #if 0 |
| 106 if ([aType type] == '{') |
| 107 return [structureTable replacementForType:aType]; |
| 108 |
| 109 if ([aType type] == '(') |
| 110 return [unionTable replacementForType:aType]; |
| 111 #endif |
| 112 return nil; |
| 113 } |
| 114 |
| 115 - (NSString *)typeFormatter:(CDTypeFormatter *)aFormatter typedefNameForStruct:(
CDType *)structType level:(NSUInteger)level; |
| 116 { |
| 117 //CDType *searchType; |
| 118 //CDStructureTable *targetTable; |
| 119 |
| 120 if (level == 0 && aFormatter == structDeclarationTypeFormatter) |
| 121 return nil; |
| 122 |
| 123 if ([self shouldExpandType:structType] == NO) |
| 124 return [self typedefNameForType:structType]; |
| 125 |
| 126 return nil; |
| 127 } |
| 128 |
| 129 - (void)appendStructuresToString:(NSMutableString *)resultString symbolReference
s:(CDSymbolReferences *)symbolReferences; |
| 130 { |
| 131 [structureTable appendNamedStructuresToString:resultString formatter:structD
eclarationTypeFormatter symbolReferences:symbolReferences |
| 132 markName:@"Named Structures"]; |
| 133 [structureTable appendTypedefsToString:resultString formatter:structDeclarat
ionTypeFormatter symbolReferences:symbolReferences |
| 134 markName:@"Typedef'd Structures"]; |
| 135 |
| 136 [unionTable appendNamedStructuresToString:resultString formatter:structDecla
rationTypeFormatter symbolReferences:symbolReferences |
| 137 markName:@"Named Unions"]; |
| 138 [unionTable appendTypedefsToString:resultString formatter:structDeclarationT
ypeFormatter symbolReferences:symbolReferences |
| 139 markName:@"Typedef'd Unions"]; |
| 140 } |
| 141 |
| 142 // Call this before calling generateMemberNames. |
| 143 - (void)generateTypedefNames; |
| 144 { |
| 145 [structureTable generateTypedefNames]; |
| 146 [unionTable generateTypedefNames]; |
| 147 } |
| 148 |
| 149 - (void)generateMemberNames; |
| 150 { |
| 151 [structureTable generateMemberNames]; |
| 152 [unionTable generateMemberNames]; |
| 153 } |
| 154 |
| 155 // |
| 156 // Run phase 1+ |
| 157 // |
| 158 |
| 159 - (void)workSomeMagic; |
| 160 { |
| 161 [self startPhase1]; |
| 162 [self startPhase2]; |
| 163 [self startPhase3]; |
| 164 |
| 165 [self generateTypedefNames]; |
| 166 [self generateMemberNames]; |
| 167 |
| 168 if (debug) { |
| 169 NSMutableString *str; |
| 170 |
| 171 str = [NSMutableString string]; |
| 172 [structureTable appendNamedStructuresToString:str formatter:structDeclar
ationTypeFormatter symbolReferences:nil |
| 173 markName:@"Named Structures"]; |
| 174 [unionTable appendNamedStructuresToString:str formatter:structDeclaratio
nTypeFormatter symbolReferences:nil |
| 175 markName:@"Named Unions"]; |
| 176 [str writeToFile:@"/tmp/out.struct" atomically:NO encoding:NSUTF8StringE
ncoding error:NULL]; |
| 177 |
| 178 str = [NSMutableString string]; |
| 179 [structureTable appendTypedefsToString:str formatter:structDeclarationTy
peFormatter symbolReferences:nil |
| 180 markName:@"Typedef'd Structures"]; |
| 181 [unionTable appendTypedefsToString:str formatter:structDeclarationTypeFo
rmatter symbolReferences:nil |
| 182 markName:@"Typedef'd Unions"]; |
| 183 [str writeToFile:@"/tmp/out.typedef" atomically:NO encoding:NSUTF8String
Encoding error:NULL]; |
| 184 //NSLog(@"str =\n%@", str); |
| 185 } |
| 186 } |
| 187 |
| 188 // |
| 189 // Phase 0 |
| 190 // |
| 191 |
| 192 - (void)phase0RegisterStructure:(CDType *)aStructure usedInMethod:(BOOL)isUsedIn
Method; |
| 193 { |
| 194 if ([aStructure type] == '{') { |
| 195 [structureTable phase0RegisterStructure:aStructure usedInMethod:isUsedIn
Method]; |
| 196 } else if ([aStructure type] == '(') { |
| 197 [unionTable phase0RegisterStructure:aStructure usedInMethod:isUsedInMeth
od]; |
| 198 } else { |
| 199 NSLog(@"%s, unknown structure type: %d", _cmd, [aStructure type]); |
| 200 } |
| 201 } |
| 202 |
| 203 - (void)endPhase:(NSUInteger)phase; |
| 204 { |
| 205 if (phase == 0) { |
| 206 [structureTable finishPhase0]; |
| 207 [unionTable finishPhase0]; |
| 208 } |
| 209 } |
| 210 |
| 211 // |
| 212 // Phase 1 |
| 213 // |
| 214 |
| 215 // Phase one builds a list of all of the named and unnamed structures. |
| 216 // It does this by going through all the top level structures we found in phase
0. |
| 217 - (void)startPhase1; |
| 218 { |
| 219 //NSLog(@" > %s", _cmd); |
| 220 // Structures and unions can be nested, so do phase 1 on each table before f
inishing the phase. |
| 221 [structureTable phase1WithTypeController:self]; |
| 222 [unionTable phase1WithTypeController:self]; |
| 223 |
| 224 [structureTable finishPhase1]; |
| 225 [unionTable finishPhase1]; |
| 226 //NSLog(@"< %s", _cmd); |
| 227 } |
| 228 |
| 229 - (void)phase1RegisterStructure:(CDType *)aStructure; |
| 230 { |
| 231 if ([aStructure type] == '{') { |
| 232 [structureTable phase1RegisterStructure:aStructure]; |
| 233 } else if ([aStructure type] == '(') { |
| 234 [unionTable phase1RegisterStructure:aStructure]; |
| 235 } else { |
| 236 NSLog(@"%s, unknown structure type: %d", _cmd, [aStructure type]); |
| 237 } |
| 238 } |
| 239 |
| 240 // |
| 241 // Phase 2 |
| 242 // |
| 243 |
| 244 - (void)startPhase2; |
| 245 { |
| 246 NSUInteger maxDepth, depth; |
| 247 |
| 248 //NSLog(@" > %s", _cmd); |
| 249 |
| 250 maxDepth = [structureTable phase1_maxDepth]; |
| 251 if (maxDepth < [unionTable phase1_maxDepth]) |
| 252 maxDepth = [unionTable phase1_maxDepth]; |
| 253 |
| 254 if (debug) NSLog(@"max structure/union depth is: %u", maxDepth); |
| 255 |
| 256 for (depth = 1; depth <= maxDepth; depth++) { |
| 257 [structureTable phase2AtDepth:depth typeController:self]; |
| 258 [unionTable phase2AtDepth:depth typeController:self]; |
| 259 } |
| 260 |
| 261 //[structureTable logPhase2Info]; |
| 262 [structureTable finishPhase2]; |
| 263 [unionTable finishPhase2]; |
| 264 } |
| 265 |
| 266 - (void)startPhase3; |
| 267 { |
| 268 // do phase2 merge on all the types from phase 0 |
| 269 [structureTable phase2ReplacementOnPhase0WithTypeController:self]; |
| 270 [unionTable phase2ReplacementOnPhase0WithTypeController:self]; |
| 271 |
| 272 // Any info referenced by a method, or with >1 reference, gets typedef'd. |
| 273 // - Generate name hash based on full type string at this point |
| 274 // - Then fill in unnamed fields |
| 275 |
| 276 // Print method/>1 ref names and typedefs |
| 277 // Go through all updated phase0_structureInfo types |
| 278 // - start merging these into a new table |
| 279 // - If this is the first time a structure has been added: |
| 280 // - add one reference for each subtype |
| 281 // - otherwise just merge them. |
| 282 // - end result should be CDStructureInfos with counts and method reference
flags |
| 283 [structureTable buildPhase3Exceptions]; |
| 284 [unionTable buildPhase3Exceptions]; |
| 285 |
| 286 [structureTable phase3WithTypeController:self]; |
| 287 [unionTable phase3WithTypeController:self]; |
| 288 |
| 289 [structureTable finishPhase3]; |
| 290 [unionTable finishPhase3]; |
| 291 //[structureTable logPhase3Info]; |
| 292 |
| 293 // - All named structures (minus exceptions like struct _flags) get declared
at the top level |
| 294 // - All anonymous structures (minus exceptions) referenced by a method |
| 295 // OR references >1 time gets typ
edef'd at the top and referenced by typedef subsequently |
| 296 // Celebrate! |
| 297 |
| 298 // Then... what do we do when printing ivars/method types? |
| 299 // CDTypeController - (BOOL)shouldExpandType:(CDType *)type; |
| 300 // CDTypeController - (NSString *)typedefNameForType:(CDType *)type; |
| 301 |
| 302 //NSLog(@"< %s", _cmd); |
| 303 } |
| 304 |
| 305 - (BOOL)shouldShowName:(NSString *)name; |
| 306 { |
| 307 return ([nonretained_classDump shouldMatchRegex] == NO) || [nonretained_clas
sDump regexMatchesString:name]; |
| 308 } |
| 309 |
| 310 - (BOOL)shouldShowIvarOffsets; |
| 311 { |
| 312 return nonretained_classDump.shouldShowIvarOffsets; |
| 313 } |
| 314 |
| 315 - (BOOL)shouldShowMethodAddresses; |
| 316 { |
| 317 return nonretained_classDump.shouldShowMethodAddresses; |
| 318 } |
| 319 |
| 320 - (BOOL)targetArchUses64BitABI; |
| 321 { |
| 322 return CDArchUses64BitABI(nonretained_classDump.targetArch); |
| 323 } |
| 324 |
| 325 - (CDType *)phase2ReplacementForType:(CDType *)type; |
| 326 { |
| 327 if ([type type] == '{') |
| 328 return [structureTable phase2ReplacementForType:type]; |
| 329 |
| 330 if ([type type] == '(') |
| 331 return [unionTable phase2ReplacementForType:type]; |
| 332 |
| 333 return nil; |
| 334 } |
| 335 |
| 336 - (void)phase3RegisterStructure:(CDType *)aStructure; |
| 337 { |
| 338 //NSLog(@"%s, type= %@", _cmd, [aStructure typeString]); |
| 339 if ([aStructure type] == '{') |
| 340 [structureTable phase3RegisterStructure:aStructure count:1 usedInMethod:
NO typeController:self]; |
| 341 |
| 342 if ([aStructure type] == '(') |
| 343 [unionTable phase3RegisterStructure:aStructure count:1 usedInMethod:NO t
ypeController:self]; |
| 344 } |
| 345 |
| 346 - (CDType *)phase3ReplacementForType:(CDType *)type; |
| 347 { |
| 348 if ([type type] == '{') |
| 349 return [structureTable phase3ReplacementForType:type]; |
| 350 |
| 351 if ([type type] == '(') |
| 352 return [unionTable phase3ReplacementForType:type]; |
| 353 |
| 354 return nil; |
| 355 } |
| 356 |
| 357 - (BOOL)shouldExpandType:(CDType *)type; |
| 358 { |
| 359 if ([type type] == '{') |
| 360 return [structureTable shouldExpandType:type]; |
| 361 |
| 362 if ([type type] == '(') |
| 363 return [unionTable shouldExpandType:type]; |
| 364 |
| 365 return NO; |
| 366 } |
| 367 |
| 368 - (NSString *)typedefNameForType:(CDType *)type; |
| 369 { |
| 370 if ([type type] == '{') |
| 371 return [structureTable typedefNameForType:type]; |
| 372 |
| 373 if ([type type] == '(') |
| 374 return [unionTable typedefNameForType:type]; |
| 375 |
| 376 return nil; |
| 377 } |
| 378 |
| 379 @end |
OLD | NEW |