pygccxml.msvc.pdb.loader

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
     43 -def print_files( session ):
     44      files = iter( session.findFile( None, '', 0 ) )
     45      for f in files:
     46          f = ctypes.cast( f, ctypes.POINTER(msdia.IDiaSourceFile) )
     47          print 'File: ', f.fileName
     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