Package pygccxml :: Package msvc :: Package pdb :: Module loader

Source Code for Module pygccxml.msvc.pdb.loader

  1  import os 
  2  import re 
  3  import pdb 
  4  import sys 
  5  import ctypes 
  6  import pprint 
  7  import logging 
  8  import comtypes 
  9  import itertools 
 10  import comtypes.client 
 11   
 12  from . import enums 
 13  from . import impl_details 
 14   
 15  from ... import utils 
 16  from ... import declarations 
 17  from .. import config as msvc_cfg 
 18  from .. import common_utils as msvc_utils 
 19   
 20  msdia = comtypes.client.GetModule( msvc_cfg.msdia_path ) 
 21   
 22  SymTagEnum = 12 
 23  msdia.SymTagEnum = 12 
24 25 -def iif( condition, true_value, false_value ):
26 if condition: 27 return true_value 28 else: 29 return false_value
30
31 -def as_symbol( x ):
32 return ctypes.cast( x, ctypes.POINTER( msdia.IDiaSymbol ) )
33
34 -def as_table( x ):
35 return ctypes.cast( x, ctypes.POINTER( msdia.IDiaTable ) )
36
37 -def as_enum_symbols( x ):
38 return ctypes.cast( x, ctypes.POINTER( msdia.IDiaEnumSymbols ) )
39
40 -def as_enum_variant( x ):
41 return ctypes.cast( x, ctypes.POINTER( comtypes.automation.IEnumVARIANT ) )
42 48
49 -class decl_loader_t(object):
50 COMPILER = declarations.compilers.MSVC_PDB_9
51 - def __init__(self, pdb_file_path ):
52 self.logger = utils.loggers.pdb_reader 53 self.logger.setLevel(logging.INFO) 54 self.logger.debug( 'creating DiaSource object' ) 55 self.__dia_source = comtypes.client.CreateObject( msdia.DiaSource ) 56 self.logger.debug( 'loading pdb file: %s' % pdb_file_path ) 57 self.__dia_source.loadDataFromPdb(pdb_file_path) 58 self.logger.debug( 'opening session' ) 59 self.__dia_session = self.__dia_source.openSession() 60 self.logger.debug( 'opening session - done' ) 61 self.__global_ns = declarations.namespace_t( '::' ) 62 self.__global_ns.compiler = self.COMPILER 63 self.__id2decl = {} #cache symIndexId : decl 64 self.__types_cache = {} #smbl id : type
65
66 - def __find_table(self, name):
67 valid_names = ( 'Symbols', 'SourceFiles', 'Sections' 68 , 'SegmentMap', 'InjectedSource', 'FrameData' ) 69 tables = self.__dia_session.getEnumTables() 70 for table in itertools.imap(as_table, tables): 71 if name == table.name: 72 return table 73 else: 74 return None
75 76 @utils.cached
77 - def symbols_table(self):
78 return self.__find_table( "Symbols" )
79 80 @utils.cached
81 - def symbols(self):
82 self.logger.info( 'loading symbols from the file' ) 83 smbls = {} 84 for smbl in itertools.imap( as_symbol, as_enum_variant( self.symbols_table._NewEnum ) ): 85 smbl.uname = msvc_utils.undecorate_name( smbl.name, msvc_utils.UNDECORATE_NAME_OPTIONS.UNDNAME_SCOPES_ONLY ) 86 def smbl_undecorate_name( options = None ): 87 return msvc_utils.undecorate_name( smbl.name, options )
88 smbl.undecorate_name = smbl_undecorate_name 89 smbls[ smbl.symIndexId ] = smbl 90 self.logger.info( 'loading symbols(%d) from the file - done', len( smbls ) ) 91 return smbls
92
93 - def __load_nss(self):
94 def ns_filter( smbl ): 95 self.logger.debug( '__load_ns.ns_filter, %s', smbl.uname ) 96 tags = ( msdia.SymTagFunction 97 , msdia.SymTagBlock 98 , msdia.SymTagData 99 #~ , msdia.SymTagAnnotation 100 #~ , msdia.SymTagPublicSymbol 101 , msdia.SymTagUDT 102 , msdia.SymTagEnum 103 #~ , msdia.SymTagFunctionType 104 #~ , msdia.SymTagPointerType 105 , msdia.SymTagArrayType 106 , msdia.SymTagBaseType 107 , msdia.SymTagTypedef 108 , msdia.SymTagBaseClass 109 , msdia.SymTagFriend 110 #~ , msdia.SymTagFunctionArgType 111 #~ , msdia.SymTagUsingNamespace 112 ) 113 if smbl.symTag not in tags: 114 self.logger.debug( 'smbl.symTag not in tags, %s', smbl.uname ) 115 return False 116 elif smbl.symTag == msdia.SymTagData and not self.__is_my_var( smbl ): 117 return False 118 elif not smbl.name: 119 self.logger.debug( 'not smbl.name, %s', smbl.uname ) 120 return False 121 #~ elif '-' in smbl.name: 122 #~ self.logger.debug( '"-" in smbl.name, %s', smbl.uname ) 123 #~ return False 124 elif smbl.classParent: 125 parent_smbl = self.symbols[ smbl.classParentId ] 126 while parent_smbl: 127 if parent_smbl.symTag == msdia.SymTagUDT: 128 if parent_smbl.uname in smbl.uname: 129 #for some reason std::map is reported as parent of std::_Tree, in source code 130 #std::map derives from std::_Tree. In logical sense parent name is a subset of the child name 131 self.logger.debug( 'parent_smbl.symTag == msdia.SymTagUDT, %s', parent_smbl.uname ) 132 return False 133 else: 134 return True 135 else: 136 parent_smbl = self.symbols[ parent_smbl.classParentId ] 137 else: 138 return True
139 140 self.logger.debug( 'scanning symbols table' ) 141 142 self.logger.debug( 'looking for scopes' ) 143 names = set() 144 for index, smbl in enumerate( itertools.ifilter( ns_filter, self.symbols.itervalues() ) ): 145 if index and ( index % 10000 == 0 ): 146 self.logger.debug( '%d symbols scanned', index ) 147 name_splitter = impl_details.get_name_splitter( smbl.uname ) 148 for sn in name_splitter.scope_names: 149 if '<' in sn: 150 break 151 else: 152 names.add( sn ) 153 names = list( names ) 154 names.sort() 155 self.logger.debug( 'looking for scopes - done' ) 156 157 nss = {'': self.__global_ns} 158 159 self.logger.debug( 'building namespace objects' ) 160 for ns_name in itertools.ifilterfalse( self.__find_udt, names ): 161 self.logger.debug( 'inserting ns "%s" into declarations tree', ns_name ) 162 name_splitter = impl_details.get_name_splitter( ns_name ) 163 if not name_splitter.scope_names: 164 parent_ns = self.global_ns 165 else: 166 parent_ns = nss.get( name_splitter.scope_names[-1], None ) 167 if not parent_ns: 168 continue #in this case the parent scope is UDT 169 ns_decl = declarations.namespace_t( name_splitter.name ) 170 ns_decl.compiler = self.COMPILER 171 ns_decl.mangled = ns_decl.name 172 ns_decl.demangled = ns_decl.name 173 parent_ns.adopt_declaration( ns_decl ) 174 nss[ ns_name ] = ns_decl 175 self.logger.debug( 'inserting ns "%s" into declarations tree - done', ns_name ) 176 self.logger.debug( 'building namespace objects - done' ) 177 178 self.logger.debug( 'scanning symbols table - done' ) 179
180 - def __update_decls_tree( self, decl ):
181 #~ if decl.name == 'money_base' and isinstance( decl, declarations.class_t ): 182 #~ pdb.set_trace() 183 smbl = decl.dia_symbols[0] 184 if smbl.classParentId in self.__id2decl: 185 self.__adopt_declaration( self.__id2decl[smbl.classParentId], decl ) 186 else: 187 name_splitter = impl_details.get_name_splitter( smbl.uname ) 188 if not name_splitter.scope_names: 189 self.__adopt_declaration( self.global_ns, decl ) 190 else: 191 parent_name = '::' + name_splitter.scope_names[-1] 192 try: 193 parent = self.global_ns.decl( parent_name ) 194 except: 195 declarations.print_declarations( self.global_ns ) 196 print 'identifiers:' 197 for index, identifier in enumerate(name_splitter.identifiers): 198 print index, ':', identifier 199 raise 200 self.__adopt_declaration( parent, decl )
201
202 - def __adopt_declaration( self, parent, decl ):
203 smbl = decl.dia_symbols[0] 204 already_added = parent.decls( decl.name, decl_type=decl.__class__, recursive=False, allow_empty=True ) 205 if not already_added: 206 if isinstance( parent, declarations.namespace_t ): 207 parent.adopt_declaration( decl ) 208 else: 209 parent.adopt_declaration( decl, self.__guess_access_type( smbl ) ) 210 self.__id2decl[ smbl.symIndexId ] = decl 211 else: 212 for other_decl in already_added: 213 if self.__is_same_smbls( other_decl, decl ): 214 other_decl.dia_symbols.append( smbl ) 215 self.__id2decl[ smbl.symIndexId ] = other_decl 216 return 217 else: 218 if isinstance( parent, declarations.namespace_t ): 219 parent.adopt_declaration( decl ) 220 else: 221 parent.adopt_declaration( decl, self.__guess_access_type( smbl ) ) 222 self.__id2decl[ smbl.symIndexId ] = decl
223
224 - def __guess_access_type( self, smbl ):
225 if enums.CV_access_e.CV_private == smbl.access: 226 return declarations.ACCESS_TYPES.PRIVATE 227 elif enums.CV_access_e.CV_protected == smbl.access: 228 return declarations.ACCESS_TYPES.PROTECTED 229 else: 230 fully_undecorated_name = smbl.undecorate_name() 231 if fully_undecorated_name.startswith( 'private:' ): 232 declarations.ACCESS_TYPES.PRIVATE 233 elif fully_undecorated_name.startswith( 'protected:' ): 234 declarations.ACCESS_TYPES.PROTECTED 235 else: 236 return declarations.ACCESS_TYPES.PUBLIC
237
238 - class parent_exists_t:
239 - def __init__( self, global_ns, classes, id2decl ):
240 self.global_ns = global_ns 241 self.classes = classes 242 self.id2decl = id2decl 243 self.__parent_exist = set()
244
245 - def __call__( self, decl ):
246 smbl = decl.dia_symbols[0] 247 if smbl.classParent: 248 if smbl.classParentId in self.id2decl: 249 return True 250 else: 251 return False 252 if self.classes.has_key( smbl.classParentId ): 253 return False 254 name_splitter = impl_details.get_name_splitter( smbl.uname ) 255 if not name_splitter.scope_names: 256 return True #global namespace 257 else: 258 #print "I am here " + '::' + name_splitter.scope_names[-1] 259 parent_name = '::' + name_splitter.scope_names[-1] 260 if parent_name in self.__parent_exist: 261 return True 262 found = self.global_ns.decls( parent_name 263 , decl_type=declarations.scopedef_t 264 , allow_empty=True 265 , recursive=True ) 266 if found: 267 self.__parent_exist.add( parent_name ) 268 return bool( found )
269
270 - def __clear_symbols(self):
271 self.logger.info( 'clearing symbols' ) 272 to_be_deleted = [] 273 useless_tags = ( 274 msdia.SymTagAnnotation 275 , msdia.SymTagPublicSymbol 276 , msdia.SymTagBlock 277 , msdia.SymTagFuncDebugStart 278 , msdia.SymTagFuncDebugEnd 279 ) 280 for smbl_id, smbl in self.symbols.iteritems(): 281 if smbl.symTag in useless_tags \ 282 or ( smbl.symTag == msdia.SymTagData and not self.__is_my_var( smbl ) ): 283 to_be_deleted.append( smbl_id ) 284 285 map( lambda smbl_id: self.symbols.pop( smbl_id ), to_be_deleted ) 286 self.logger.info( 'clearing symbols(%d) - done', len( to_be_deleted ) )
287 288
289 - def __normalize_name( self, decl ):
290 if decl.name == '<unnamed-tag>': 291 decl.name = '' 292 elif decl.name.startswith( '?' ): 293 decl.name = '' 294 elif isinstance( decl, declarations.namespace_t ) and 'anonymous-namespace' in decl.name: 295 decl.name = '' 296 else: 297 pass
298
299 - def __join_unnamed_nss( self, ns_parent ):
300 child_nss = ns_parent.namespaces( name='', recursive=False, allow_empty=True ) 301 if len(child_nss) > 1: 302 alive_ns = child_nss[0] 303 dead_nss = child_nss[1:] 304 for dead_ns in dead_nss: 305 decls = dead_ns.decls( recursive=False, allow_empty=True ) 306 map( dead_ns.remove_declaration, decls ) 307 map( alive_ns.adopt_declaration, decls ) 308 map( ns_parent.remove_declaration, dead_nss ) 309 map( self.__join_unnamed_nss 310 , ns_parent.namespaces( recursive=False, allow_empty=True ) )
311 312
313 - def read(self):
314 self.__clear_symbols() 315 self.__load_nss() 316 self.__load_classes() 317 self.__load_base_classes() 318 self.__load_enums() 319 self.__load_vars() 320 self.__load_typedefs() 321 self.__load_calldefs() 322 map( self.__normalize_name, self.global_ns.decls(recursive=True) ) 323 self.__join_unnamed_nss( self.global_ns )
324 #join unnamed namespaces 325 326 @property
327 - def dia_global_scope(self):
328 return self.__dia_session.globalScope
329 330 @property
331 - def global_ns(self):
332 return self.__global_ns
333
334 - def __is_same_smbls( self, decl1, decl2 ):
335 if not( decl1.__class__ is decl2.__class__ ): 336 return False 337 if decl1.name == decl2.name: 338 if isinstance( decl1, declarations.calldef_t ): 339 #TODO: well, I will have to fix this someday 340 return False 341 else: 342 return True 343 else: 344 return False
345 #~ return self.__dia_session.symsAreEquiv( decl1.dia_symbols[0], decl2.dia_symbols[0] ) 346
347 - def __find_udt( self, name ):
348 self.logger.debug( 'testing whether name( "%s" ) is UDT symbol' % name ) 349 flags = enums.NameSearchOptions.nsfCaseSensitive 350 found = self.dia_global_scope.findChildren( msdia.SymTagUDT, name, flags ) 351 if found.Count == 1: 352 self.logger.debug( 'name( "%s" ) is UDT symbol' % name ) 353 return as_symbol( found.Item(0) ) 354 elif 1 < found.Count: 355 raise RuntimeError( "duplicated UDTs with name '%s', were found" % name ) 356 #~ self.logger.debug( 'name( "%s" ) is UDT symbol' % name ) 357 #~ return [as_symbol( s ) for s in iter(found)] 358 #~ for s in iter(found): 359 #~ s = 360 #~ print s.name 361 #~ print impl_details.guess_class_type(s.udtKind) 362 else: 363 self.logger.debug( 'name( "%s" ) is **NOT** UDT symbol' % name ) 364 return None
365
366 - def __update_decl( self, decl, smbl ):
367 decl.dia_symbols = [smbl] 368 decl.compiler = self.COMPILER 369 if not isinstance( decl, declarations.typedef_t ): 370 decl.byte_size = smbl.length 371 decl.byte_offset = smbl.offset 372 decl.mangled = iif( smbl.get_undecoratedNameEx(0), smbl.name, '' ) 373 decl.demangled = iif( smbl.uname, smbl.uname, '' ) 374 decl.is_artificial = bool( smbl.compilerGenerated ) 375 decl.location = declarations.location_t( smbl.lexicalParent.sourceFileName )
376 377
378 - def __load_classes( self ):
379 classes = {}#unique symbol id : class decl 380 is_udt = lambda smbl: smbl.symTag == msdia.SymTagUDT 381 self.logger.info( 'building udt objects' ) 382 for udt_smbl in itertools.ifilter( is_udt, self.symbols.itervalues() ): 383 classes[udt_smbl.symIndexId] = self.__create_class(udt_smbl) 384 self.logger.info( 'building udt objects(%d) - done', len(classes) ) 385 386 self.logger.info( 'integrating udt objects with namespaces' ) 387 does_parent_exists = self.parent_exists_t( self.global_ns, classes, self.__id2decl ) 388 while classes: 389 to_be_integrated = len( classes ) 390 self.logger.info( 'there are %d classes to go', len( classes ) ) 391 to_be_deleted = filter( does_parent_exists, classes.itervalues() ) 392 map( self.__update_decls_tree, to_be_deleted ) 393 map( lambda decl: classes.pop( decl.dia_symbols[0].symIndexId ) 394 , to_be_deleted ) 395 if not ( to_be_integrated - len( classes ) ): 396 for cls in classes.itervalues(): 397 self.logger.warning( 'unable to integrate class "%s" into declarations tree', cls.dia_symbols[0].uname ) 398 break 399 self.logger.info( 'integrating udt objects with namespaces - done' )
400
401 - def __load_base_classes( self ):
402 make_hi = declarations.hierarchy_info_t 403 is_base_class = lambda smbl: smbl.symTag == msdia.SymTagBaseClass \ 404 and False == smbl.indirectVirtualBaseClass 405 self.logger.info( 'building class hierarchies' ) 406 for count, smbl in enumerate( itertools.ifilter( is_base_class, self.symbols.itervalues() ) ): 407 base_id = smbl.type.symIndexId 408 derived_id = smbl.classParentId 409 410 hi_base = make_hi( self.__id2decl[base_id] 411 , self.__guess_access_type( smbl ) 412 , bool( smbl.virtualBaseClass ) ) 413 self.__id2decl[ derived_id ].bases.append( hi_base ) 414 415 hi_derived = make_hi( self.__id2decl[derived_id] 416 , self.__guess_access_type( smbl ) 417 , bool( smbl.virtualBaseClass ) ) 418 self.__id2decl[ base_id ].derived.append( hi_derived ) 419 420 self.logger.info( 'building class hierarchies(%d) - done', count )
421
422 - def __load_enums( self ):
423 is_enum = lambda smbl: smbl.symTag == msdia.SymTagEnum 424 self.logger.info( 'building enum objects' ) 425 for enums_count, enum_smbl in enumerate( itertools.ifilter( is_enum, self.symbols.itervalues() ) ): 426 enum_decl = self.__create_enum(enum_smbl) 427 if not enum_decl: 428 continue 429 self.__update_decls_tree( enum_decl ) 430 self.logger.info( 'building enum objects(%d) - done', enums_count )
431
432 - def __create_enum( self, enum_smbl ):
433 name_splitter = impl_details.get_name_splitter( enum_smbl.uname ) 434 self.logger.debug( 'working on enum %s', enum_smbl.uname ) 435 enum_decl = declarations.enumeration_t( name_splitter.name ) 436 self.__update_decl( enum_decl, enum_smbl ) 437 438 values = enum_smbl.findChildren( msdia.SymTagData, None, 0 ) 439 for v in itertools.imap(as_symbol, values): 440 if v.classParent.symIndexId != enum_smbl.symIndexId: 441 continue 442 enum_decl.append_value( v.name, v.value ) 443 if enum_decl.values: 444 return enum_decl 445 else: 446 #for some reason same enum could appear under global namespace and 447 #under the class, it was defined in. This is a criteria I use to distinguish 448 #between those cases 449 return None
450
451 - def __create_class( self, class_smbl ):
452 name_splitter = impl_details.get_name_splitter( class_smbl.uname ) 453 class_decl = declarations.class_t( name_splitter.name ) 454 self.__update_decl( class_decl, class_smbl ) 455 class_decl.class_type = impl_details.guess_class_type(class_smbl.udtKind) 456 return class_decl
457
458 - def __is_my_var( self, smbl ):
459 #I am only interested in global and class variables 460 if smbl.symTag != msdia.SymTagData: 461 return False 462 if not smbl.uname: 463 return False 464 if smbl.classParentId not in self.symbols: 465 return True #global scope 466 parent_smbl = self.symbols[ smbl.classParentId ] 467 return bool( parent_smbl.symTag == msdia.SymTagUDT )
468
469 - def __load_vars( self ):
470 self.logger.info( 'building variable objects' ) 471 472 for vars_count, var_smbl in enumerate( itertools.ifilter( self.__is_my_var, self.symbols.itervalues() ) ): 473 var_decl = self.__create_var(var_smbl) 474 if var_decl: 475 self.__update_decls_tree( var_decl ) 476 self.logger.info( 'building variable objects(%d) - done', vars_count )
477
478 - def __create_var( self, smbl ):
479 self.logger.debug( 'creating variable "%s"', smbl.uname ) 480 name_splitter = impl_details.get_name_splitter( smbl.uname ) 481 decl = declarations.variable_t( name_splitter.name ) 482 self.__update_decl( decl, smbl ) 483 decl.type = self.create_type( smbl.type ) 484 decl.value = str(smbl.value) 485 self.logger.debug( 'creating variable "%s" - done', smbl.uname ) 486 return decl
487
488 - def __load_typedefs( self ):
489 self.logger.info( 'building typedef objects' ) 490 is_typedef = lambda smbl: smbl.symTag == msdia.SymTagTypedef 491 for typedefs_count, typedef_smbl in enumerate( itertools.ifilter( is_typedef, self.symbols.itervalues() ) ): 492 typedef_decl = self.__create_typedef(typedef_smbl) 493 self.__update_decls_tree( typedef_decl ) 494 self.logger.info( 'building typedef objects(%d) - done', typedefs_count )
495
496 - def __create_typedef( self, smbl ):
497 self.logger.debug( 'creating typedef "%s"', smbl.uname ) 498 name_splitter = impl_details.get_name_splitter( smbl.uname ) 499 decl = declarations.typedef_t( name_splitter.name 500 , self.create_type( smbl.type ) ) 501 self.__update_decl( decl, smbl ) 502 self.logger.debug( 'creating typedef "%s" - done', smbl.uname ) 503 return decl
504
505 - def __load_calldefs( self ):
506 self.logger.info( 'building function objects' ) 507 is_function = lambda smbl: smbl.symTag == msdia.SymTagFunction 508 for functions_count, function_smbl in enumerate( itertools.ifilter( is_function, self.symbols.itervalues() ) ): 509 function_decl = self.__create_calldef(function_smbl) 510 if function_decl: 511 self.__update_decls_tree( function_decl ) 512 self.logger.info( 'building function objects(%d) - done', functions_count )
513
514 - def __guess_operator_type( self, smbl, operator_type ):
515 #assumption: the code deals with correct code 516 if not smbl.uname.startswith( 'operator' ) or smbl.uname == 'operator': 517 return None 518 oper_smbls = ('!', ' ', '*', '%', '&', '(', '+', '-', ',', '/', '|', '~', '[', '^', '=', '<') 519 if smbl.uname[ len( 'operator' ) ] not in oper_smbls: 520 return None 521 if smbl.uname[ len( 'operator' ) ] == ' ' \ 522 and smbl.uname not in ['operator new', 'operator delete']: 523 #we have casting operator 524 return declarations.casting_operator_t() 525 if isinstance( operator_type, declarations.member_function_type_t ): 526 return declarations.member_operator_t() 527 else: 528 return declarations.free_operator_t()
529
530 - def __guess_constructor( self, smbl, calldef_type ):
531 tmpls = declarations.templates 532 class_ = declarations.remove_declarated( calldef_type.class_inst ) 533 if class_.name == smbl.uname \ 534 or ( tmpls.is_instantiation( class_.name ) 535 and tmpls.name( class_.name ) == smbl.uname ): 536 calldef_type.return_type = None 537 return declarations.constructor_t()
538
539 - def __create_calldef( self, smbl ):
540 self.logger.debug( 'creating calldef "%s"', smbl.uname ) 541 #~ if smbl.uname == 'some_function': 542 #~ pdb.set_trace() 543 name_splitter = impl_details.get_name_splitter( smbl.uname ) 544 calldef_type = self.create_type( smbl.type ) #what does happen with constructor? 545 decl = None 546 if isinstance( calldef_type, declarations.member_function_type_t ): 547 could_be_static = False 548 could_be_const = False 549 if smbl.uname.startswith( '~' ): 550 decl = declarations.destructor_t() 551 if not decl: #may be operator 552 decl = self.__guess_operator_type(smbl, calldef_type) 553 could_be_static = True 554 could_be_const = True 555 if not decl: #may be constructor 556 decl = self.__guess_constructor( smbl, calldef_type ) 557 if not decl: 558 decl = declarations.member_function_t() 559 could_be_static = True 560 could_be_const = True 561 if smbl.virtual: 562 decl.virtuality = iif( smbl.pure 563 , declarations.VIRTUALITY_TYPES.PURE_VIRTUAL 564 , declarations.VIRTUALITY_TYPES.VIRTUAL ) 565 decl.has_const = bool( could_be_const and smbl.constType ) 566 decl.has_static = bool( could_be_static and smbl.isStatic ) 567 else: 568 decl = self.__guess_operator_type(smbl, calldef_type) 569 if not decl: 570 if 'instantiate::`dynamic initializer for' in smbl.uname: 571 return #in this case we deal with initializer of some global variable 572 decl = declarations.free_function_t() 573 decl.name = smbl.uname 574 decl.arguments = map( lambda t: declarations.argument_t( type=t ) 575 , calldef_type.arguments_types ) 576 577 args_smbls = map( as_symbol, smbl.findChildren( msdia.SymTagData, None, 0 ) ) 578 args_smbls = filter( lambda smbl: smbl.dataKind == enums.DataKind.DataIsParam, args_smbls ) 579 580 for index, arg_smbl in enumerate( args_smbls ): 581 arg_decl = decl.arguments[index] 582 arg_decl.name = arg_smbl.name 583 arg_decl.default_value = arg_smbl.value 584 decl.return_type = calldef_type.return_type 585 586 self.__update_decl( decl, smbl ) 587 self.logger.debug( 'creating calldef "%s" - done', smbl.uname ) 588 return decl
589
590 - def __create_function_type( self, smbl ):
591 return_type = self.create_type( smbl.type ) 592 args_smbls = smbl.findChildren( msdia.SymTagFunctionArgType, None, 0 ) 593 args_types = map( self.create_type, itertools.imap(as_symbol, args_smbls) ) 594 if smbl.objectPointerType: 595 try: 596 class_ = self.create_type( smbl.objectPointerType ) 597 class_ = declarations.base_type( class_ ) 598 #~ pdb.set_trace() 599 return declarations.member_function_type_t( class_, return_type, args_types ) 600 except: 601 self.logger.warning( 'unable to find out the type of the object pointer for a class method.' ) 602 return declarations.unknown_t() 603 else: 604 return declarations.free_function_type_t( return_type, args_types )
605
606 - def create_type( self, smbl ):
607 #http://msdn2.microsoft.com/en-us/library/s3f49ktz(VS.80).aspx 608 if smbl.symIndexId in self.__types_cache: 609 return self.__types_cache[smbl.symIndexId] 610 my_type = None 611 if msdia.SymTagBaseType == smbl.symTag: 612 if enums.BasicType.btNoType == smbl.baseType: 613 my_type = declarations.unknown_t() 614 elif enums.BasicType.btVoid == smbl.baseType: 615 my_type = declarations.void_t() 616 elif enums.BasicType.btChar == smbl.baseType: 617 my_type = declarations.char_t() 618 elif enums.BasicType.btWChar == smbl.baseType: 619 my_type = declarations.wchar_t() 620 elif smbl.baseType in ( enums.BasicType.btInt, enums.BasicType.btLong ): 621 if 8 == smbl.length: 622 my_type = declarations.long_long_int_t() 623 elif 4 == smbl.length: 624 my_type = declarations.int_t() #long_int_t 625 elif 2 == smbl.length: 626 my_type = declarations.short_int_t() 627 else: 628 my_type = declarations.int_t() 629 elif enums.BasicType.btUInt == smbl.baseType: 630 if 2 == smbl.length: 631 my_type = declarations.short_unsigned_int_t() 632 else: 633 my_type = declarations.unsigned_int_t() 634 elif enums.BasicType.btFloat == smbl.baseType: 635 if 8 == smbl.length: 636 my_type = declarations.double_t() 637 else: 638 my_type = declarations.float_t() 639 elif enums.BasicType.btBCD == smbl.baseType: 640 my_type = declarations.unknown_t() 641 elif enums.BasicType.btBool == smbl.baseType: 642 my_type = declarations.bool_t() 643 elif enums.BasicType.btULong == smbl.baseType: 644 if 8 == smbl.length: 645 my_type = declarations.long_long_unsigned_int_t() 646 else: 647 my_type = declarations.long_unsigned_int_t() 648 elif enums.BasicType.btCurrency == smbl.baseType: 649 my_type = declarations.unknown_t() 650 elif enums.BasicType.btDate == smbl.baseType: 651 my_type = declarations.double_t() 652 elif enums.BasicType.btVariant == smbl.baseType: 653 my_type = declarations.unknown_t() 654 elif enums.BasicType.btComplex == smbl.baseType: 655 my_type = declarations.complex_double_t() 656 elif enums.BasicType.btBit == smbl.baseType: 657 my_type = declarations.unknown_t() 658 elif enums.BasicType.btBSTR == smbl.baseType: 659 my_type = declarations.unknown_t() 660 elif enums.BasicType.btHresult == smbl.baseType: 661 my_type = declarations.long_int_t() 662 else: 663 my_type = declarations.unknown_t() 664 elif msdia.SymTagPointerType == smbl.symTag: 665 base_type = self.create_type( smbl.type ) 666 if smbl.reference: 667 my_type = declarations.reference_t( base_type ) 668 else: 669 my_type = declarations.pointer_t( base_type ) 670 elif msdia.SymTagArrayType == smbl.symTag: 671 element_type = self.create_type( smbl.type ) 672 size = declarations.array_t.SIZE_UNKNOWN 673 if smbl.count: 674 size = smbl.count 675 #~ if smbl.length and element_type.byte_size: 676 #~ size = smbl.length / element_type.byte_size 677 my_type = declarations.array_t( element_type, size ) 678 elif smbl.symTag in ( msdia.SymTagUDT, msdia.SymTagTypedef, msdia.SymTagEnum ): 679 if smbl.symIndexId in self.__id2decl: 680 decl = self.__id2decl[ smbl.symIndexId ] 681 my_type = declarations.declarated_t( decl ) 682 else: 683 my_type = declarations.unknown_t() 684 elif msdia.SymTagFunctionArgType == smbl.symTag: 685 my_type = self.create_type( smbl.type ) 686 elif msdia.SymTagFunctionType == smbl.symTag: 687 my_type = self.__create_function_type( smbl ) 688 else: 689 my_type = declarations.unknown_t() 690 try: 691 my_type.byte_size = smbl.length 692 except AttributeError: 693 pass 694 if smbl.constType: 695 if isinstance( my_type, declarations.member_function_type_t ): 696 my_type.has_const = True 697 else: 698 if not isinstance( my_type, declarations.const_t ): 699 my_type = declarations.const_t( my_type ) 700 if smbl.volatileType: 701 if not isinstance( my_type, declarations.volatile_t ): 702 my_type = declarations.volatile_t( my_type ) 703 return my_type
704