Dia2dump.cpp Source File
Note
This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here
The following Dia2dump.cpp source code displays the contents of a .pdb file. This source code is used by Dia2dump Sample.
// 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);
}
void Error( const char *msg )
{
printf( " **error: %s\n", msg );
}
class CDiaBSTR
{
BSTR m_bstr;
public:
CDiaBSTR() { m_bstr = NULL; }
~CDiaBSTR() { if (m_bstr != NULL) SysFreeString( m_bstr ); }
BSTR *operator &() { assert(m_bstr == NULL); return &m_bstr; }
operator BSTR() { assert(m_bstr != NULL); return m_bstr; }
};
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;
CDiaBSTR 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 );
}
}
void printType( IDiaSymbol* pType )
{
DWORD tag = 0;
pType->get_symTag( &tag );
CDiaBSTR name;
if ( pType->get_name( &name ) == S_OK && name != NULL ) {
printf( "-%ws", 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 ];
if ( psyms == NULL ) {
Fatal( "out of memory" );
}
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 ];
if ( pdata == NULL ) {
Fatal( "out of memory" );
}
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;
CDiaBSTR 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 ] );
}
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;
CDiaBSTR name;
if ( pSym->get_symTag( &tag ) != S_OK )
Fatal( "Internal error, no SymTag" );
if ( pSym->get_name( &name ) != S_OK )
Fatal( "Internal error, no name" );
// tagtype name found in name or scopeTag
wprintf( L"\t%ws %ws found in ", szTags[ tag ], name );
printScopeName( pscope );
wprintf( L"\n" );
pSym = 0;
}
}
void FindNameInNamespace( wchar_t* name, IDiaSymbol* pnamespace )
{
wchar_t *buf = NULL;
CDiaBSTR szNamespace;
pnamespace->get_name( &szNamespace );
buf = new wchar_t[ wcslen( name ) + wcslen( szNamespace ) + 3];
if ( buf == NULL ) {
Fatal( "out of memory" );
}
wsprintfW( buf, L"%s::%s", szNamespace, name );
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;
// is this 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 ) {
CDiaBSTR 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 when 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 );
CDiaBSTR 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 );
}
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" );
CDiaBSTR name;
if ( pSymbol->get_name( &name ) == S_OK && name != NULL ) {
printf( "%ws", 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 )/sizeof( wszFilename[0] ) );
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 ) {
CDiaBSTR name;
if ( pSymbol->get_name( &name ) != S_OK )
Fatal( "get_name" );
printf( "Found UDT: %ws\n", name );
ULONGLONG len = 0;
pSymbol->get_length( &len );
if ( len == 0 ) {
Error( "could not 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 ) {
CDiaBSTR bstrTableName;
if ( pTable->get_name( &bstrTableName ) != 0 )
Fatal( "get_name" );
printf( "Found table: %ws\n", bstrTableName );
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 );
CDiaBSTR name;
if ( pSymbol->get_name( &name ) == S_OK && name != NULL ) {
printf( "sym name: %ws", name );
if ( symTag == SymTagPublicSymbol ) {
CDiaBSTR undName;
pSymbol->get_undecoratedName( &undName );
printf( " (%ws)", undName );
}
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 ) {
CDiaBSTR name;
DWORD tag;
pfuncSym->get_symTag( &tag );
pfuncSym->get_name( &name );
printf( "\tfound alt symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
}
} 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 ) {
CDiaBSTR fileName;
if ( pSourceFile->get_fileName( &fileName) == S_OK ) {
printf( "file name: %ws\n", fileName );
}
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 ) {
CDiaBSTR name;
DWORD tag;
pSym->get_symTag( &tag );
pSym->get_name( &name );
printf( "\tClosest symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
}
} else {
printf( "Segment %i \n", seg );
pSegment = NULL;
CComPtr<IDiaSymbol> pSym;
if ( SUCCEEDED( psession->findSymbolByAddr( seg, 0, SymTagNull, &pSym ) ) ) {
CDiaBSTR name;
DWORD tag;
pSym->get_symTag( &tag );
pSym->get_name( &name );
printf( "\tClosest symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
}
}
}
} 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 ) {
CDiaBSTR name;
DWORD tag;
pSym->get_symTag( &tag );
pSym->get_name( &name );
printf( " symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
} 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 ) ) ) {
CDiaBSTR name;
DWORD tag;
pSym->get_symTag( &tag );
pSym->get_name( &name );
printf( " symbol: %ws (%ws)\n", name != NULL ? name : L"", szTags[ tag ] );
} 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[] = {
"msdia71.dll",
"..\\bin\\msdia71.dll",
"..\\..\\bin\\msdia71.dll",
0
};
int main(int argc, char* argv[])
{
if ( argc < 2 ) {
usage(argc, argv);
}
HRESULT hr;
hr = CoInitialize(NULL);
if (FAILED(hr))
{
Fatal("CoInitialize failed\n");
}
CComPtr<IDiaDataSource> pSource;
// Initialize The Component Object Module Library
// Obtain Access To The Provider
hr = CoCreateInstance( CLSID_DiaSource, NULL, CLSCTX_INPROC_SERVER,
__uuidof( IDiaDataSource ), (void **) &pSource);
if (FAILED(hr))
{
Fatal("Could not CoCreate CLSID_DiaSource. Register msdia71.dll." );
}
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;
pSource = 0;
CoUninitialize();
return 0;
}