This documentation is archived and is not being maintained.

Dia2dump.cpp Source File

The source code for Dia2dump.cpp follows.

// dia2dump.cpp : Dump contents of a pdb file using DIA.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------
//

#include "stdafx.h"
#include "diacreate.h"
#include "cvconst.h"

void Fatal( const char *msg )
{
   printf( msg );
   printf( "\n" );
   exit( -1 );
}

#ifdef NOCOM

#define freeString LocalFree

#else

#define freeString SysFreeString

#endif

CComPtr<IDiaSession> psession;
CComPtr<IDiaSymbol> pglobal;

void printVariant( VARIANT& v )
{
   switch( v.vt )
   {
 //*   LONGLONG      VT_I8
   case VT_I8:
      printf( "%ld", v.llVal );
      break;
 //*   LONG         VT_I4
   case VT_I4:
      printf( "%d", v.lVal );
      break;
 //*   BYTE         VT_UI1
   case VT_UI1:
      printf( "%d", v.bVal);
      break;
 //*   SHORT         VT_I2
   case VT_I2:
      printf( "%d", v.iVal);
      break;
 //*   CHAR         VT_I1
   case VT_I1:
      printf( "%d", v.cVal);
      break;
 //*   USHORT         VT_UI2
   case VT_UI2:
      printf( "%d", v.uiVal);
      break;
//*   ULONG         VT_UI4
   case VT_UI4:
      printf( "%d", v.ulVal);
      break;
 //*   ULONGLONG         VT_UI8
   case VT_UI8:
      printf( "%ld", v.ullVal);
      break;
 //*   INT         VT_INT
   case VT_INT:
      printf( "%d", v.intVal);
      break;
 //*   UINT         VT_UINT
   case VT_UINT:
      printf( "%d", v.uintVal);
      break;
   default:
      printf( "<Not implemented>" );
      break;
   }
}

void printBound( IDiaSymbol* pBound )
{
   DWORD tag = 0;
   BSTR name;
   DWORD kind;
   pBound->get_symTag( &tag );
   pBound->get_locationType( &kind );
   if ( tag == SymTagData && kind == LocIsConstant ) {
      CComVariant v;
      pBound->get_value( &v );
      printVariant( v );
   } else if ( pBound->get_name( &name ) == S_OK ) {
      printf( "%ws", name );
      freeString( name );
   }
}

void printType( IDiaSymbol* pType )
{
   DWORD tag = 0;
   pType->get_symTag( &tag );
   BSTR name;
   if ( pType->get_name( &name ) == S_OK && name != NULL ) {
      printf( "-%ws", name );
      freeString( name );
   } else if ( tag == SymTagPointerType ) {
      CComPtr<IDiaSymbol> pBaseType;
      if (  pType->get_type( &pBaseType ) == S_OK ) {
         printType( pBaseType );
         printf( "*" );
      } else {
         Fatal( "pointer get_type" );
      }
   } else if ( tag == SymTagBaseType ) {
      ULONGLONG size;
      DWORD bt;
      if ( pType->get_length( &size ) != S_OK )
         Fatal( "Internal error, no Length" );
      if ( pType->get_baseType( &bt ) != S_OK )
         Fatal( "Internal error, no baseType" );
       wprintf( L"(base type=%d, len=%ld)  ", bt, size );
   } else if ( tag == SymTagArrayType ) {
      CComPtr<IDiaSymbol> pBaseType;
      if ( pType->get_type( &pBaseType ) == S_OK ) {
         printType( pBaseType );
      } else {
         Fatal( "array get_type" );
      }
      DWORD rank;
      DWORD celt;
      LONG count;
      CComPtr< IDiaEnumSymbols > pEnum;
      if ( pType->get_rank( &rank ) == S_OK ) {
         if ( pType->findChildren( SymTagDimension, NULL, nsNone, &pEnum ) == S_OK && pEnum != NULL ) {
            CComPtr< IDiaSymbol > pSym;
            while ( pEnum->Next( 1, &pSym, &celt ) == S_OK && celt == 1 ) {
               CComPtr< IDiaSymbol > pBound;
               printf( "[" );
               if ( pSym->get_lowerBound( &pBound ) == S_OK ) {
                  printBound( pBound );
                  printf("..");
               }
               pBound = NULL;
               if ( pSym->get_upperBound( &pBound ) == S_OK ) {
                  printBound( pBound );
               }
               pBound = NULL;
               printf( "]" );
               pSym = NULL;

            }
         } 
      } else if ( pType->findChildren( SymTagCustomType, NULL, nsNone, &pEnum ) == S_OK && pEnum != NULL && SUCCEEDED( pEnum->get_Count( &count ) ) && count > 0 ){
            CComPtr< IDiaSymbol > pSym;
            while ( pEnum->Next( 1, &pSym, &celt ) == S_OK && celt == 1 ) {
               printf( "[" );
               printType( pSym );
               printf( "]" );
               pSym = NULL;
            }
      } else {
         ULONGLONG lenArray;
         ULONGLONG lenElem;
         if ( pType->get_length( &lenArray ) != S_OK
            || pBaseType->get_length( &lenElem ) != S_OK ) {
            Fatal( "No type length." );
         }
         printf( "[%ld]", lenArray/lenElem );
      }
   } else if ( tag == SymTagFunctionType ) {
      printf( "Function Type" );
   } else if ( tag == SymTagCustomType ) {
      printf( "Custom Type: " );
      DWORD id;
      DWORD rec;
      GUID guid;
      if ( pType->get_guid( &guid ) == S_OK ) {
         wchar_t wszGuid[64];
         StringFromGUID2(guid, wszGuid, 64);
         printf( "%ws", wszGuid );
      } else if ( pType->get_oemId( &id ) == S_OK && pType->get_oemSymbolId( &rec ) == S_OK ) {
         printf( "%x:%x", id, rec );
      }
      DWORD len = 0;
      if ( pType->get_types( 0, &len, NULL ) == S_OK && len > 0 ) {
         IDiaSymbol** psyms = new IDiaSymbol*[ len ];
         pType->get_types( len, &len, psyms );
         for ( DWORD i = 0; i < len; ++i ) {
            printf( " <" );
            printType( psyms[i] );
            printf( ">" );
            psyms[i]->Release();
         }
         delete [] psyms;
      }
      len = 0;
      if ( pType->get_dataBytes( 0, &len, NULL ) == S_OK && len > 0 ) {
         BYTE* pdata = new BYTE[ len ];
         pType->get_dataBytes( len, &len, pdata );
         printf( "<data" );
         for ( DWORD i = 0; i < len; ++i ) {
            printf( " %02x", pdata[i] );
         }
         printf( " data>" );
         delete [] pdata;
      }
   } else {
      printf( "No Type.");
   }
}

void dumpFunctionLines( IDiaSymbol* pSymbol, IDiaSession* pSession )
{
   ULONGLONG length = 0;
   DWORD isect = 0;
   DWORD offset = 0;
   pSymbol->get_addressSection( &isect );
   pSymbol->get_addressOffset( &offset );
   pSymbol->get_length( &length );
   if ( isect != 0 && length > 0 ) {
      CComPtr< IDiaEnumLineNumbers > pLines;
      if ( SUCCEEDED( pSession->findLinesByAddr( isect, offset, static_cast<DWORD>( length ), &pLines ) ) ) {
         CComPtr< IDiaLineNumber > pLine;
         DWORD celt;
         bool firstLine = true;
         while ( SUCCEEDED( pLines->Next( 1, &pLine, &celt ) ) && celt == 1 ){
            DWORD offset;
            DWORD seg;
            DWORD linenum;
            CComPtr< IDiaSymbol > pComp;
            CComPtr< IDiaSourceFile > pSrc;
            pLine->get_compiland( &pComp );
            pLine->get_sourceFile( &pSrc );
            pLine->get_addressSection( &seg );
            pLine->get_addressOffset( &offset );
            pLine->get_lineNumber( &linenum );
            printf( "\tline %d at 0x%x:0x%x\n", linenum, seg, offset );
            pLine = NULL;
            if ( firstLine ) {
               // Sanity check.
               CComPtr< IDiaEnumLineNumbers > pLinesByLineNum;
               if ( SUCCEEDED( pSession->findLinesByLinenum( pComp, pSrc, linenum, 0, &pLinesByLineNum ) ) ) {
                  CComPtr< IDiaLineNumber > pLine;
                  DWORD celt;
                  while ( SUCCEEDED( pLinesByLineNum->Next( 1, &pLine, &celt ) ) && celt == 1 ){
                     DWORD offset;
                     DWORD seg;
                     DWORD linenum;
                     pLine->get_addressSection( &seg );
                     pLine->get_addressOffset( &offset );
                     pLine->get_lineNumber( &linenum );
                     printf( "\t\tfound line %d at 0x%x:0x%x\n", linenum, seg, offset );
                     pLine = NULL;
                  }
               }
               firstLine = false;
            }
         }
      }
   }
}

wchar_t* szTags[] = {
   L"",
   L"Executable (Global)",
   L"Compiland", 
   L"CompilandDetails", 
   L"CompilandEnv",
   L"Function", 
   L"Block",
   L"Data",
   L"Unused", 
   L"Label", 
   L"PublicSymbol", 
   L"UDT", 
   L"Enum", 
   L"FunctionType", 
   L"PointerType", 
   L"ArrayType", 
   L"BaseType", 
   L"Typedef", 
   L"BaseClass",
   L"Friend",
   L"FunctionArgType", 
   L"FuncDebugStart", 
   L"FuncDebugEnd",
   L"UsingNamespace", 
   L"VTableShape",
   L"VTable",
   L"Custom",
   L"Thunk",
   L"CustomType",
   L""
};

bool fTagScopes[] = {
   false,
   true,
   true, 
   false, 
   false,
   true, 
   true,
   false,
   false, 
   false, 
   false, 
   false, 
   false, 
   false, 
   false, 
   false, 
   false, 
   false, 
   false,
   false,
   false, 
   false, 
   false,
   false, 
   false,
   false,
   false,
   false,
   false,
   false
};

wchar_t* szDataKinds[] = {
   L"Unknown",
   L"Local",
   L"Static Local",
   L"Parameter",
   L"Object Pointer",
   L"File Static",
   L"Global",
   L"Member",
   L"Static Member",
   L"Constant"
};

wchar_t* symbolTagName( DWORD tag )
{
   if ( tag > SymTagNull && tag < SymTagMax )
      return szTags[ tag ];
   assert( false );
   return L"Error!";
}

bool isScopeSym( DWORD tag )
{
   if ( tag > SymTagNull && tag < SymTagMax )
      return fTagScopes[ tag ];
   assert( false );
   return false;
}

void printScopeName( IDiaSymbol* pscope )
{
   DWORD tag;
   BSTR name;
   if ( pscope->get_symTag( &tag ) != S_OK )
      Fatal( "Internal error, getting SymTag" );
   if ( pscope->get_name( &name ) != S_OK )
      Fatal( "Internal error, getting name" );
   if ( name == NULL ) {
      wprintf( szTags[ tag ] );
      return;
   }
   wprintf( L"%ws (%ws)", name, szTags[ tag ] );
   freeString( name );
}

void PrintNameFromScope( wchar_t* name, IDiaSymbol* pscope, IDiaEnumSymbols* pEnum )
{
   CComPtr< IDiaSymbol> pSym;
   DWORD celt;
   while ( SUCCEEDED( pEnum->Next( 1, &pSym, &celt ) ) && celt == 1 ) {
      DWORD tag;
      BSTR bstr;
      if ( pSym->get_symTag( &tag ) != S_OK )
         Fatal( "Internal error, no SymTag" );
      if ( pSym->get_name( &bstr ) != S_OK )
         Fatal( "Internal error, no name" );
      // Tagtype name found in name or scopeTag.
      wprintf( L"\t%ws %ws found in ", szTags[ tag ], bstr );
      printScopeName( pscope );
      wprintf( L"\n" );
      freeString( bstr );
      pSym = 0;
   }
}

void FindNameInNamespace( wchar_t* name, IDiaSymbol* pnamespace )
{
   wchar_t *buf = NULL;
   BSTR szNamespace;
   pnamespace->get_name( &szNamespace );
   buf = new wchar_t[ wcslen( name ) + wcslen( szNamespace ) + 3];
   wsprintfW( buf, L"%s::%s", szNamespace, name );
   freeString( szNamespace );
   CComPtr< IDiaEnumSymbols > pEnum;
   if ( FAILED( pglobal->findChildren( SymTagNull, name, nsCaseSensitive, &pEnum ) ) )
      Fatal( "Namespace findChildren failed" );
   long cnt = 0;
   if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found a name.
      PrintNameFromScope( name, pglobal, pEnum );
   }
   delete [] buf;
}

void FindNameInEnum( wchar_t* name, IDiaSymbol* penumeration )
{
   CComPtr< IDiaEnumSymbols > pEnum;
   if ( FAILED( penumeration->findChildren( SymTagData, name, nsRegularExpression, &pEnum ) ) )
      Fatal( "Enumeration findChildren failed" );
   long cnt = 0;
   if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found a name.
      PrintNameFromScope( name, penumeration, pEnum );
   }
}

void FindNameInClass( wchar_t* name, IDiaSymbol* pclass )
{
   CComPtr< IDiaEnumSymbols > pEnum;
   if ( FAILED( pclass->findChildren( SymTagNull, name, nsCaseSensitive, &pEnum ) ) ) 
      Fatal( "Class findChildren failed" );
   long cnt = 0;
   if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found a name.
      PrintNameFromScope( name, pclass, pEnum );
   }
   pEnum = 0;
   // Check out the enumerations.
   CComPtr< IDiaSymbol > pSym;
   if ( FAILED( pclass->findChildren( SymTagEnum, NULL, nsNone, &pEnum ) ) ) 
      Fatal( "Class findChildren for enums failed" );
   if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found an enum.
      DWORD celt;
      while ( SUCCEEDED( pEnum->Next( 1, &pSym, &celt ) ) && celt == 1 ) {
         FindNameInEnum( name, pSym );
         pSym = 0;
      }
   }
   pEnum = 0;
   // Check out the base classes.
   if ( FAILED( pclass->findChildren( SymTagBaseClass, NULL, nsNone, &pEnum ) ) ) 
      Fatal( "Class findChildren for base classes failed" );
   if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found a base class.
      DWORD celt;
      while ( SUCCEEDED( pEnum->Next( 1, &pSym, &celt ) ) && celt == 1 ) {
         CComPtr< IDiaSymbol > pClass;
         if (  pSym->get_type( &pClass ) == S_OK )
            Fatal( "Getting class for a base type failed" );
         if ( pClass )
            FindNameInClass( name, pClass );
         pSym = 0;
      }
   }
}

void FindCppNameInScope( wchar_t* name, IDiaSymbol* pScope )
{
   // while ( scope ) {
      // Scan the scope for a symbol.
      // If any namespaces, then scan for name in namespace.
      // If scope is a member function then 
      //   scan class parent for member with name.
      // scope = scope.parent;
   // }

   wprintf( L"Finding name \"%ws\" in ", name );
   printScopeName( pScope );
   wprintf( L"\n" );

   DWORD celt;
   long cnt = 0;
   CComPtr< IDiaSymbol > pSym;
   CComPtr< IDiaSymbol > pParent;
   CComPtr< IDiaSymbol > pscope;
   for ( pscope = pScope; pscope != NULL; ) {
      CComPtr< IDiaEnumSymbols > pEnum;
      // Local data search
      if ( FAILED( pscope->findChildren( SymTagNull, name, nsCaseSensitive, &pEnum ) ) )
         Fatal( "Local scope findChildren failed" );
      if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found a name.
         PrintNameFromScope( name, pscope, pEnum );
      }
      pEnum = 0;
      // Look into any namespaces.
      if ( FAILED( pscope->findChildren( SymTagUsingNamespace, NULL, nsNone, &pEnum ) ) )
         Fatal( "Namespace findChildren failed" );
      if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) {   // Found a namespace.
         while ( SUCCEEDED( pEnum->Next( 1, &pSym, &celt ) ) && celt == 1 ) {
            FindNameInNamespace( name, pSym );
            pSym = 0;
         }
      }
      pEnum = 0;
      // Check if this is a member function.
      DWORD tag = SymTagNull;
      if ( SUCCEEDED( pscope->get_symTag( &tag ) ) 
         && tag == SymTagFunction
         && SUCCEEDED( pscope->get_classParent( &pParent ) )
         && pParent != NULL ) {
         FindNameInClass( name, pParent );
      }
      pParent = NULL;
      // Move to lexical parent.
      if ( SUCCEEDED( pscope->get_lexicalParent( &pParent ) )
         && pParent != NULL ) {
         pscope = pParent;
      } else {
         pscope = NULL;
      }
      pParent = NULL;
   };
}

void dumpLocalVars( DWORD rva )
{
   CComPtr< IDiaSymbol > pBlock;
   if ( FAILED( psession->findSymbolByRVA( rva, SymTagBlock, &pBlock ) ) ) {
      Fatal( "Failed to find symbols by RVA" );
   }
   CComPtr< IDiaSymbol > pscope;
   for ( ; pBlock != NULL; ) {
      CComPtr< IDiaEnumSymbols > pEnum;
      // Local data search
      if ( FAILED( pBlock->findChildren( SymTagNull, NULL, nsNone, &pEnum ) ) )
         Fatal( "Local scope findChildren failed" );
      CComPtr< IDiaSymbol > pSymbol;
      DWORD tag;
      DWORD celt;
      while ( pEnum != NULL && SUCCEEDED( pEnum->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) {
         pSymbol->get_symTag( &tag );
         if ( tag == SymTagData ) {
            BSTR name;
            DWORD kind;
            pSymbol->get_name( &name );
            pSymbol->get_dataKind( &kind );
            if ( name != NULL )
               wprintf( L"\t%s (%s)\n", name, szDataKinds[ kind ] );
         } else if ( tag == SymTagAnnotation ) {
            CComPtr< IDiaEnumSymbols > pValues;
            // Local data search
            wprintf( L"\tAnnotation:\n" );
            if ( FAILED( pSymbol->findChildren( SymTagNull, NULL, nsNone, &pValues ) ) )
               Fatal( "Annotation findChildren failed" );
            pSymbol = NULL;
            while ( pValues != NULL && SUCCEEDED( pValues->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) {
               CComVariant value;
               if ( pSymbol->get_value( &value ) != S_OK )
                  Fatal( "No value for annotation data." );
               wprintf( L"\t\t%ws\n", value.bstrVal );
               pSymbol = NULL;
            }
         }
         pSymbol = NULL;
      }
      pBlock->get_symTag( &tag ); 
      if ( tag == SymTagFunction )   // Stop at function scope.
         break;
      // Move to lexical parent.
      CComPtr< IDiaSymbol > pParent;
      if ( SUCCEEDED( pBlock->get_lexicalParent( &pParent ) )
         && pParent != NULL ) {
         pBlock = pParent;
      } else {
         Fatal( "Finding lexical parent failed." );
      }
   };
}

DWORD PrintNameAddr( IDiaSymbol* pSym )
{
   DWORD rva;
   if ( pSym->get_relativeVirtualAddress( &rva ) != S_OK )
      rva = 0;   // No RVA; must be an absolute value.
   DWORD tag;
   pSym->get_symTag( &tag );
   BSTR name;
   if ( pSym->get_name( &name ) != S_OK )
      printf( "\t0x%08X (%ws) <no name>\n", rva, szTags[ tag ] );
   else {
      printf( "\t0x%08X (%ws) %ws\n", rva, szTags[ tag ], name );
      freeString( name );
   }
   return rva;
}

void      
DumpLex( IDiaSymbol* pscope, int tabs )
{
   HRESULT   hr;

   CComPtr<IDiaEnumSymbols> pSymbols;   
   if ( SUCCEEDED( pscope->findChildren( SymTagNull, NULL, nsNone, &pSymbols ) ) ) {
      CComPtr<IDiaSymbol> pSymbol;
      ULONG celt = 0;
      while ( pSymbols != NULL && SUCCEEDED( hr = pSymbols->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) {
         for ( int i = 0; i < tabs; ++i )
            printf( "\t" );
         BSTR name;
         if ( pSymbol->get_name( &name ) == S_OK && name != NULL ) {
            printf( "%ws", name );
            freeString( name );
         }
         DWORD symTag;
         pSymbol->get_symTag( &symTag );
         printf( " : %ws\n", szTags[ symTag ] );
         switch ( symTag ) {
         case SymTagExe:
            assert( false );
            break;
         case SymTagCompiland:
         case SymTagFunction:
         case SymTagBlock:
            DumpLex( pSymbol, tabs+1 );
            break;
         default:
            break;
         }
         pSymbol = NULL;
      }
   }
}

void      
Dump(
   char *szFilename,
   IDiaDataSource* pSource,
   wchar_t* szLookup
)
{
   HRESULT   hr;
   wchar_t wszFilename[ _MAX_PATH ];
   mbstowcs( wszFilename, szFilename, sizeof( wszFilename ) );
   if ( FAILED( pSource->loadDataFromPdb( wszFilename ) ) ) 
      if ( FAILED( pSource->loadDataForExe( wszFilename, NULL, NULL ) ) ) 
         Fatal( "loadDataFromPdb/Exe" );

   if ( FAILED( pSource->openSession( &psession ) ) ) 
      Fatal( "openSession" );
   if ( FAILED( psession->get_globalScope( &pglobal) ) )
      Fatal( "get_globalScope" );
   DWORD id = 0;
   pglobal->get_symIndexId( &id );
   if ( id == 0 )
      Fatal( "get_indexId" );

   ULONG celt = 0;

   CComPtr<IDiaEnumSymbols> pEnum;
   CComPtr<IDiaSymbol> pSymbol;

   pglobal->findChildren(SymTagUDT,NULL,nsfCaseInsensitive|nsfUndecoratedName,&pEnum);
   while ( SUCCEEDED( hr = pEnum->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) {
      BSTR name;
      if ( pSymbol->get_name( &name ) != S_OK )
         Fatal( "get_name" );
      printf( "Found UDT: %ws\n", name );
      freeString( name );
      ULONGLONG len = 0;
      pSymbol->get_length( &len );
      if ( len == 0 )
         Fatal( "get_length" );
      pSymbol = 0;
   }

   CComPtr<IDiaEnumTables> pTables;
   if ( FAILED( psession->getEnumTables( &pTables ) ) )
      Fatal( "getEnumTables" );
   CComPtr< IDiaTable > pTable;
   while ( SUCCEEDED( hr = pTables->Next( 1, &pTable, &celt ) ) && celt == 1 ) {
      BSTR name;
      if ( pTable->get_name( &name ) != 0 )
         Fatal( "get_name" );
      printf( "Found table: %ws\n", name );
      freeString( name );
      CComPtr<IDiaEnumSymbols> pSymbols;
      CComPtr<IDiaEnumSourceFiles> pSourceFiles;
      CComPtr<IDiaEnumSegments> pSegments;
      CComPtr<IDiaEnumSectionContribs> pSecContribs;
      if ( SUCCEEDED( pTable->QueryInterface( _uuidof( IDiaEnumSymbols ), (void**)&pSymbols ) ) ) {
         CComPtr<IDiaSymbol> pSymbol;
         while ( SUCCEEDED( hr = pSymbols->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) {
            DWORD symIndex;
            pSymbol->get_symIndexId( &symIndex );
            DWORD symTag;
            pSymbol->get_symTag( &symTag );
            if ( pSymbol->get_name( &name ) == S_OK && name != NULL ) {
               printf( "sym name: %ws", name );
               freeString( name );
               if ( symTag == SymTagPublicSymbol ) {
                  pSymbol->get_undecoratedName( &name );
                  printf( " (%ws)", name );
                  freeString( name );
               }
               CComPtr<IDiaSymbol> pType;
               if ( pSymbol->get_type( &pType ) == S_OK ) {
                  printf( " has type " );
                  printType( pType );

                  DWORD id = 0;
                  CComPtr< IDiaSymbol > ptypeSym;
                  pSymbol->get_typeId( &id );
                  if ( FAILED( psession->symbolById( id, &ptypeSym ) ) ||
                     psession->symsAreEquiv( pType, ptypeSym ) != S_OK ) {
                        Fatal( "Sym type equality" );
                  }
               }
               printf( "\n" );
               if ( symTag == SymTagFunction ) {
                  dumpFunctionLines( pSymbol, psession );
                  DWORD loctype;
                  if ( pSymbol->get_locationType( &loctype ) == S_OK && loctype == LocIsStatic ) {
                     DWORD rva;
                     pSymbol->get_relativeVirtualAddress( &rva );
                     if ( rva != 0 ) {
                        dumpLocalVars( rva );

                        CComPtr< IDiaSymbol > pfuncSym;
                        if ( SUCCEEDED( psession->findSymbolByRVA( rva, SymTagNull, &pfuncSym ) ) ) {
                           if ( psession->symsAreEquiv( pfuncSym, pSymbol ) != S_OK ) {
                              BSTR name;
                              DWORD tag;
                              pfuncSym->get_symTag( &tag );
                              pfuncSym->get_name( &name );
                              printf( "\tfound alt symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
                              if ( name )
                                 freeString( name );
                           }
                        } else {
                           Fatal( "No function symbol found by rva." );
                        }
                     }
                  }
               } 
            } 
            if ( isScopeSym( symTag ) && szLookup ) {
               FindCppNameInScope( szLookup, pSymbol );
            }
            pSymbol = NULL;
         }
      } else if ( SUCCEEDED( pTable->QueryInterface( _uuidof( IDiaEnumSourceFiles ), (void**)&pSourceFiles ) ) ) {
         CComPtr<IDiaSourceFile> pSourceFile;
         while ( SUCCEEDED( hr = pSourceFiles->Next( 1, &pSourceFile, &celt ) ) && celt == 1 ) {
            pSourceFile->get_fileName( &name );
            if ( name != NULL ) {
               printf( "file name: %ws\n", name );
               freeString( name );
            }
            pSourceFile = NULL;
         }
      } else if ( SUCCEEDED( pTable->QueryInterface( _uuidof( IDiaEnumSegments ), (void**)&pSegments ) ) ) {
         CComPtr<IDiaSegment> pSegment;
         while ( SUCCEEDED( hr = pSegments->Next( 1, &pSegment, &celt ) ) && celt == 1 ) {
            DWORD rva;
            DWORD seg;
            pSegment->get_addressSection( &seg );
            if ( pSegment->get_relativeVirtualAddress( &rva ) == S_OK ) {
               printf( "Segment %i addr: 0x%.8X\n", seg, rva );
               pSegment = NULL;
               CComPtr<IDiaSymbol> pSym;
               if ( psession->findSymbolByRVA( rva, SymTagNull, &pSym ) == S_OK ) {
                  BSTR name = NULL;
                  DWORD tag;
                  pSym->get_symTag( &tag );
                  pSym->get_name( &name );
                  printf( "\tClosest symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
                  if ( name )
                     freeString( name );
               }
            } else {
               printf( "Segment %i \n", seg );
               pSegment = NULL;
               CComPtr<IDiaSymbol> pSym;
               if ( SUCCEEDED( psession->findSymbolByAddr( seg, 0, SymTagNull, &pSym ) ) ) {
                  BSTR name;
                  DWORD tag;
                  pSym->get_symTag( &tag );
                  pSym->get_name( &name );
                  printf( "\tClosest symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
                  if ( name )
                     freeString( name );
               }
            }
         }
      } else if ( SUCCEEDED( pTable->QueryInterface( _uuidof( IDiaEnumSectionContribs ), (void**)&pSecContribs ) ) ) {
         printf( "SecContribs\n" );
         CComPtr<IDiaSectionContrib> pSecContrib;
         while ( SUCCEEDED( hr = pSecContribs->Next( 1, &pSecContrib, &celt ) ) && celt == 1 ) {
            DWORD rva;
            if ( pSecContrib->get_relativeVirtualAddress( &rva ) == S_OK ) {
               printf( "\taddr: 0x%.8X", rva );
               pSecContrib = NULL;
               CComPtr<IDiaSymbol> pSym;
               if ( psession->findSymbolByRVA( rva, SymTagNull, &pSym ) == S_OK ) {
                  BSTR name = NULL;
                  DWORD tag;
                  pSym->get_symTag( &tag );
                  pSym->get_name( &name );
                  printf( "    symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
                  if ( name )
                     freeString( name );
               } else {
                  printf( "<no symbol found?>\n" );
               }
            } else {
               DWORD isect;
               DWORD offset;
               pSecContrib->get_addressSection( &isect );
               pSecContrib->get_addressOffset( &offset );
               printf( "\taddr: 0x%.4X:0x%.8X", isect, offset );
               pSecContrib = NULL;
               CComPtr<IDiaSymbol> pSym;
               if ( SUCCEEDED( psession->findSymbolByAddr( isect, offset, SymTagNull, &pSym ) ) ) {
                  BSTR name;
                  DWORD tag;
                  pSym->get_symTag( &tag );
                  pSym->get_name( &name );
                  printf( "    symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
                  if ( name )
                     freeString( name );
               } else {
                  printf( "<no symbol found?>\n" );
               }         
            }
         }
      }

      pTable = NULL;
   }
   CComPtr<IDiaEnumSymbolsByAddr> pEnumByAddr;
   if ( FAILED( psession->getSymbolsByAddr( &pEnumByAddr ) ) )
      Fatal( "getSymbolsByAddr" );
   CComPtr<IDiaSymbol> pSym;
   if ( FAILED( pEnumByAddr->symbolByAddr( 1, 0, &pSym ) ) )
      Fatal( "symbolByAddr" );
   DWORD rvaLast = 0;
   if ( pSym->get_relativeVirtualAddress( &rvaLast ) == S_OK ) {
      pSym = 0;
      if ( FAILED( pEnumByAddr->symbolByRVA( rvaLast, &pSym ) ) )
         Fatal( "symbolByAddr" );
      printf( "Symbols in order\n" );
      do { 
         rvaLast = PrintNameAddr( pSym );
         pSym = 0;
         celt = 0;
         if ( FAILED( hr = pEnumByAddr->Next( 1, &pSym, &celt ) ) ) 
            break;
      } while ( celt == 1 );

      printf( "Symbols in reverse order\n" );
      pSym = 0;
      if ( FAILED( pEnumByAddr->symbolByRVA( rvaLast, &pSym ) ) )
         Fatal( "symbolByRva" );
      printf( "Symbols in order\n" );
      do { 
         rvaLast = PrintNameAddr( pSym );
         pSym = 0;
         celt = 0;
         if ( FAILED( hr = pEnumByAddr->Prev( 1, &pSym, &celt ) ) ) 
            break;
      } while ( celt == 1 );

      if ( FAILED( hr ) )
         Fatal( "Next" );
   }

}

void usage( int argc, char* argv[] )
{
   printf( "usage: %s <pdb-filename>\n", argv[0] );
   exit( -1 );
}

const char* diaPaths[] = {
      "msdia20.dll",
      "..\\bin\\msdia20.dll",
      "..\\..\\bin\\msdia20.dll",
      0
};

int main(int argc, char* argv[])
{

   if ( argc < 2 ) {
      usage(argc, argv);
   }

   HRESULT   hr;
#ifndef NOCOM
   hr = CoInitialize(NULL);
   if (FAILED(hr))
   {
      Fatal("CoInitialize failed\n");
   }
#endif

   {

      CComPtr<IDiaDataSource> pSource;
      // Initialize the COM library.

#ifdef NOCOM

#ifdef NOREG
      hr = NoRegCoCreate( "msdia20.dll", _uuidof( DiaSourceAlt ), _uuidof( IDiaDataSource ), (void **) &pSource );
#else
      hr = NoOleCoCreate( _uuidof( DiaSourceAlt ), _uuidof( IDiaDataSource ), (void **) &pSource );
#endif

#else
      // Obtain access to the provider.
      hr = CoCreateInstance(_uuidof( DiaSource ), NULL, CLSCTX_INPROC_SERVER, 
         _uuidof( IDiaDataSource ), (void **) &pSource);
      if ( hr == REGDB_E_CLASSNOTREG ) {
         for ( int i = 0; FAILED( hr ) && diaPaths[i] != 0; ++i ) {
            hr = NoRegCoCreate( diaPaths[i], _uuidof( DiaSource ), _uuidof( IDiaDataSource ), (void **) &pSource );
         }
      }
#endif
      if (FAILED(hr))
      {   
         Fatal("Could not CoCreate CLSID_DiaSource(Alt). Register msdia20.dll or add its location to your PATH." );
      }
      if ( argc > 2 ) {
         wchar_t name[ 256 ];
         mbstowcs( name, argv[ 2 ], 256 );
         Dump( argv[ 1 ], pSource, name );
         DumpLex( pglobal, 0 );
      } else {
         Dump( argv[ 1 ], pSource, NULL );
      }
   }
   pglobal = 0;
   psession= 0;
#ifndef NOCOM
   CoUninitialize();
#endif
   return 0;
}

Show: