Dia2dump.cpp Source File
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;
}