GT-2975 (Closes #674): Corrections, formatting, and certification

Pulled-from: Paul Moran <paul@paulsapps.com>
This commit is contained in:
ghizard 2019-07-17 09:40:38 -04:00
parent 81b0f31f03
commit 5621f6965e
13 changed files with 264 additions and 284 deletions

View file

@ -2,6 +2,7 @@
Module.manifest||GHIDRA||||END| Module.manifest||GHIDRA||||END|
build.gradle||GHIDRA||||END| build.gradle||GHIDRA||||END|
src/global/docs/README_PDB.html||GHIDRA||||END| src/global/docs/README_PDB.html||GHIDRA||||END|
src/pdb/.editorconfig||GHIDRA||||END|
src/pdb/README.txt||GHIDRA||||END| src/pdb/README.txt||GHIDRA||||END|
src/pdb/pdb.sln||GHIDRA||||END| src/pdb/pdb.sln||GHIDRA||||END|
src/pdb/pdb.vcxproj||GHIDRA||||END| src/pdb/pdb.vcxproj||GHIDRA||||END|

View file

@ -30,7 +30,7 @@ void fatal( const char * msg )
} }
void checkErr(HRESULT hResult) { void checkErr(HRESULT hResult) {
if (SUCCEEDED(hResult)) { if (hResult == S_OK) {
return; return;
} }
switch (hResult) { switch (hResult) {

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,11 +17,10 @@
#include <atlcomcli.h> #include <atlcomcli.h>
#include <comutil.h> #include <comutil.h>
std::wstring findMangledName(PDBApiContext& ctx, IDiaSymbol& pFunction) { std::wstring findMangledName(PDBApiContext& ctx, IDiaSymbol& function) {
const DWORD rva = getRVA(pFunction); const DWORD rva = getRVA(function);
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
const HRESULT hr = ctx.Session().findSymbolByRVA(rva, SymTagPublicSymbol, &pSymbol); if (ctx.Session().findSymbolByRVA(rva, SymTagPublicSymbol, &pSymbol) == S_OK) {
if (SUCCEEDED(hr)) {
const DWORD tag = getTag(*pSymbol); const DWORD tag = getTag(*pSymbol);
if (tag == SymTagPublicSymbol) {//do not delete if (tag == SymTagPublicSymbol) {//do not delete
const DWORD address = getRVA(*pSymbol); const DWORD address = getRVA(*pSymbol);
@ -31,19 +29,16 @@ std::wstring findMangledName(PDBApiContext& ctx, IDiaSymbol& pFunction) {
} }
} }
} }
return getName(pFunction); return getName(function);
} }
void findNameInNamespace(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol& pnamespace ) void findNameInNamespace(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol& myNamespace )
{ {
BSTR temp = NULL; bstr_t bstrNamespace;
if (FAILED(pnamespace.get_name(&temp))) { if (FAILED(myNamespace.get_name(bstrNamespace.GetAddress()))) {
fatal("Namespace get_name failed"); fatal("Namespace get_name failed");
} }
bstr_t bstrNamespace;
bstrNamespace.Attach(temp);
const std::wstring strNamespace(bstrNamespace.GetBSTR(), bstrNamespace.length()); const std::wstring strNamespace(bstrNamespace.GetBSTR(), bstrNamespace.length());
const std::wstring fullName = strNamespace + L"::" + name; const std::wstring fullName = strNamespace + L"::" + name;
@ -53,81 +48,85 @@ void findNameInNamespace(PDBApiContext& ctx, const std::wstring& name, IDiaSymbo
} }
long cnt = 0; long cnt = 0;
if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) { // Found a name. if ( pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0 ) { // Found a name.
printNameFromScope(ctx.Global(), *pEnum ); printNameFromScope(ctx.Global(), *pEnum );
} }
} }
void findNameInEnum( const std::wstring& name, IDiaSymbol& penumeration ) void findNameInEnum( const std::wstring& name, IDiaSymbol& enumeration )
{ {
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
if ( FAILED( penumeration.findChildren( SymTagData, name.c_str(), nsRegularExpression, &pEnum ) ) ) { if ( FAILED( enumeration.findChildren( SymTagData, name.c_str(), nsRegularExpression, &pEnum ) ) ) {
fatal( "Enumeration findChildren failed" ); fatal( "Enumeration findChildren failed" );
} }
long cnt = 0; long cnt = 0;
if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) { // Found a name. if ( pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0 ) { // Found a name.
printNameFromScope( penumeration, *pEnum ); printNameFromScope( enumeration, *pEnum );
} }
} }
void findNameInClass( const std::wstring& name, IDiaSymbol& pclass ) // 20190716: TODO: Investigate... This function appears to be only called by
// itself and by findCppNameInScope, which currently appears to be unused.
void findNameInClass( const std::wstring& name, IDiaSymbol& myClass )
{ {
{ {
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
if (FAILED(pclass.findChildren(SymTagNull, name.c_str(), nsCaseSensitive, &pEnum))) { if (FAILED(myClass.findChildren(SymTagNull, name.c_str(), nsCaseSensitive, &pEnum))) {
fatal("Class findChildren failed"); fatal("Class findChildren failed");
} }
long cnt = 0; long cnt = 0;
if (pEnum != NULL && SUCCEEDED(pEnum->get_Count(&cnt)) && cnt > 0) { // Found a name. if (pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0) { // Found a name.
printNameFromScope(pclass, *pEnum); printNameFromScope(myClass, *pEnum);
} }
} }
{ {
// Check out the enumerations. // Check out the enumerations.
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
CComPtr<IDiaSymbol> pSym; CComPtr<IDiaSymbol> pSym;
if (FAILED(pclass.findChildren(SymTagEnum, NULL, nsNone, &pEnum))) { if (FAILED(myClass.findChildren(SymTagEnum, NULL, nsNone, &pEnum))) {
fatal("Class findChildren for enums failed"); fatal("Class findChildren for enums failed");
} }
long cnt = 0; long cnt = 0;
if (pEnum != NULL && SUCCEEDED(pEnum->get_Count(&cnt)) && cnt > 0) { // Found an enum. if (pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0) { // Found an enum.
DWORD celt; DWORD celt;
while (SUCCEEDED(pEnum->Next(1, &pSym, &celt)) && celt == 1) { while (pEnum->Next(1, &pSym, &celt) == S_OK && celt == 1) {
findNameInEnum(name, *pSym); findNameInEnum(name, *pSym);
pSym = 0; pSym = 0;
} }
} }
} }
{ {
// Check out the base classes. // Check out the base classes.
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
if (FAILED(pclass.findChildren(SymTagBaseClass, NULL, nsNone, &pEnum))) { if (FAILED(myClass.findChildren(SymTagBaseClass, NULL, nsNone, &pEnum))) {
fatal("Class findChildren for base classes failed"); fatal("Class findChildren for base classes failed");
} }
long cnt = 0; long cnt = 0;
if (pEnum != NULL && SUCCEEDED(pEnum->get_Count(&cnt)) && cnt > 0) { // Found a base class. if (pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0) { // Found a base class.
DWORD celt; DWORD celt;
CComPtr<IDiaSymbol> pSym; CComPtr<IDiaSymbol> pSym;
while (SUCCEEDED(pEnum->Next(1, &pSym, &celt)) && celt == 1) { while (pEnum->Next(1, &pSym, &celt) == S_OK && celt == 1) {
CComPtr<IDiaSymbol> pClass; CComPtr<IDiaSymbol> pClass;
if (pSym->get_type(&pClass) == S_OK) { if (pSym->get_type(&pClass) != S_OK ) {
fatal("Getting class for a base type failed"); fatal("Getting class for a base type failed");
} }
if (pClass) { if (pClass) {
findNameInClass(name, *pClass); findNameInClass(name, *pClass);
} }
pSym = 0; pSym = 0;
} }
} }
} }
} }
void findCppNameInScope(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol& pScope ) // 20190716: TODO: Investigate... This code appears to be unused. Also see
// note on function findNameInClass.
void findCppNameInScope(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol& scope )
{ {
// while ( scope ) { // while ( scope ) {
// Scan the scope for a symbol. // Scan the scope for a symbol.
@ -138,21 +137,21 @@ void findCppNameInScope(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol
// } // }
printf( "Finding name \"%S\" in ", name.c_str() ); printf( "Finding name \"%S\" in ", name.c_str() );
printScopeName( pScope ); printScopeName( scope );
printf( "\n" ); printf( "\n" );
DWORD celt; DWORD celt;
long cnt = 0; long cnt = 0;
CComPtr<IDiaSymbol> pSym; CComPtr<IDiaSymbol> pSym;
CComPtr<IDiaSymbol> pParent; CComPtr<IDiaSymbol> pParent;
CComPtr<IDiaSymbol> pscope; CComPtr<IDiaSymbol> pscope;
for ( pscope = &pScope; pscope != NULL; ) { for ( pscope = &scope; pscope != NULL; ) {
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
// Local data search // Local data search
if ( FAILED( pscope->findChildren( SymTagNull, name.c_str(), nsCaseSensitive, &pEnum ) ) ) { if ( FAILED( pscope->findChildren( SymTagNull, name.c_str(), nsCaseSensitive, &pEnum ) ) ) {
fatal( "Local scope findChildren failed" ); fatal( "Local scope findChildren failed" );
} }
if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) { // Found a name. if ( pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0 ) { // Found a name.
printNameFromScope( *pscope, *pEnum ); printNameFromScope( *pscope, *pEnum );
} }
pEnum = 0; pEnum = 0;
@ -160,8 +159,8 @@ void findCppNameInScope(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol
if ( FAILED( pscope->findChildren( SymTagUsingNamespace, NULL, nsNone, &pEnum ) ) ) { if ( FAILED( pscope->findChildren( SymTagUsingNamespace, NULL, nsNone, &pEnum ) ) ) {
fatal( "Namespace findChildren failed" ); fatal( "Namespace findChildren failed" );
} }
if ( pEnum != NULL && SUCCEEDED( pEnum->get_Count(&cnt) ) && cnt > 0 ) { // Found a namespace. if ( pEnum != NULL && pEnum->get_Count(&cnt) == S_OK && cnt > 0 ) { // Found a namespace.
while ( SUCCEEDED( pEnum->Next( 1, &pSym, &celt ) ) && celt == 1 ) { while ( pEnum->Next( 1, &pSym, &celt ) == S_OK && celt == 1 ) {
findNameInNamespace( ctx, name, *pSym ); findNameInNamespace( ctx, name, *pSym );
pSym = 0; pSym = 0;
} }
@ -169,12 +168,12 @@ void findCppNameInScope(PDBApiContext& ctx, const std::wstring& name, IDiaSymbol
pEnum = 0; pEnum = 0;
// Check if this is a member function. // Check if this is a member function.
DWORD tag = SymTagNull; DWORD tag = SymTagNull;
if ( SUCCEEDED( pscope->get_symTag( &tag ) ) && tag == SymTagFunction && SUCCEEDED( pscope->get_classParent( &pParent ) ) && pParent != NULL ) { if ( pscope->get_symTag( &tag ) == S_OK && tag == SymTagFunction && pscope->get_classParent( &pParent ) == S_OK && pParent != NULL ) {
findNameInClass( name, *pParent ); findNameInClass( name, *pParent );
} }
pParent = NULL; pParent = NULL;
// Move to lexical parent. // Move to lexical parent.
if ( SUCCEEDED( pscope->get_lexicalParent( &pParent ) ) && pParent != NULL ) { if ( pscope->get_lexicalParent( &pParent ) == S_OK && pParent != NULL ) {
pscope = pParent; pscope = pParent;
} }
else { else {

View file

@ -16,22 +16,22 @@
*/ */
#include "iterate.h" #include "iterate.h"
static void iterateEnumMembers(IDiaSymbol& pSymbol) { static void iterateEnumMembers(IDiaSymbol& symbol) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
CComPtr<IDiaSymbol> pMember; CComPtr<IDiaSymbol> pMember;
pSymbol.findChildren(SymTagNull, NULL, nsNone, &pEnum); symbol.findChildren(SymTagNull, NULL, nsNone, &pEnum);
if (pEnum == NULL) { if (pEnum == NULL) {
return; return;
} }
while (1) { while (1) {
if (FAILED(pEnum->Next( 1, &pMember, &celt ))) { if (pEnum->Next( 1, &pMember, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
break; break;
} }
std::wstring name = getName(*pMember); std::wstring name = getName(*pMember);
std::wstring value = getValue(*pMember); std::wstring value = getValue(*pMember);
printf("%S<member name=\"%S\" value=\"%S\" />\n", indent(12).c_str(), name.c_str(), value.c_str()); printf("%S<member name=\"%S\" value=\"%S\" />\n", indent(12).c_str(), name.c_str(), value.c_str());
pMember = 0; pMember = 0;
@ -41,14 +41,14 @@ static void iterateEnumMembers(IDiaSymbol& pSymbol) {
void iterateEnums(PDBApiContext& ctx) { void iterateEnums(PDBApiContext& ctx) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
ctx.Global().findChildren(SymTagEnum, NULL, nsNone, &pEnum); ctx.Global().findChildren(SymTagEnum, NULL, nsNone, &pEnum);
if (pEnum == NULL) { if (pEnum == NULL) {
return; return;
} }
printf("%S<enums>\n", indent(4).c_str()); printf("%S<enums>\n", indent(4).c_str());
while ( 1 ) { while ( 1 ) {
if (FAILED(pEnum->Next( 1, &pSymbol, &celt ))) { if (pEnum->Next( 1, &pSymbol, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -70,16 +70,16 @@ void iterateEnums(PDBApiContext& ctx) {
printf("%S</enums>\n", indent(4).c_str()); printf("%S</enums>\n", indent(4).c_str());
} }
static void iterateMembers(IDiaSymbol& pSymbol) { static void iterateMembers(IDiaSymbol& symbol) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
pSymbol.findChildren(SymTagNull, NULL, nsNone, &pEnum); symbol.findChildren(SymTagNull, NULL, nsNone, &pEnum);
if (pEnum == NULL) { if (pEnum == NULL) {
return; return;
} }
while (1) { while (1) {
CComPtr<IDiaSymbol> pMember; CComPtr<IDiaSymbol> pMember;
if (FAILED(pEnum->Next(1, &pMember, &celt))) { if (pEnum->Next(1, &pMember, &celt) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -107,7 +107,7 @@ void iterateDataTypes(PDBApiContext& ctx) {
while (1) { while (1) {
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
if (FAILED(pEnum->Next(1, &pSymbol, &celt))) { if ( pEnum->Next(1, &pSymbol, &celt) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -140,7 +140,7 @@ void iterateDataTypes(PDBApiContext& ctx) {
void iterateTypedefs(PDBApiContext& ctx) { void iterateTypedefs(PDBApiContext& ctx) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
ctx.Global().findChildren(SymTagTypedef, NULL, nsNone/*nsfCaseInsensitive|nsfUndecoratedName*/, &pEnum); ctx.Global().findChildren(SymTagTypedef, NULL, nsNone/*nsfCaseInsensitive|nsfUndecoratedName*/, &pEnum);
if (pEnum == NULL) { if (pEnum == NULL) {
return; return;
@ -148,7 +148,7 @@ void iterateTypedefs(PDBApiContext& ctx) {
printf("%S<typedefs>\n", indent(4).c_str()); printf("%S<typedefs>\n", indent(4).c_str());
while ( 1 ) { while ( 1 ) {
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
if (FAILED(pEnum->Next( 1, &pSymbol, &celt ))) { if (pEnum->Next( 1, &pSymbol, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -167,7 +167,7 @@ void iterateTypedefs(PDBApiContext& ctx) {
void iterateClasses(PDBApiContext& ctx) { void iterateClasses(PDBApiContext& ctx) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
ctx.Global().findChildren(SymTagUDT, NULL, nsNone/*nsfCaseInsensitive|nsfUndecoratedName*/, &pEnum); ctx.Global().findChildren(SymTagUDT, NULL, nsNone/*nsfCaseInsensitive|nsfUndecoratedName*/, &pEnum);
if (pEnum == NULL) { if (pEnum == NULL) {
return; return;
@ -175,7 +175,7 @@ void iterateClasses(PDBApiContext& ctx) {
printf("%S<classes>\n", indent(4).c_str()); printf("%S<classes>\n", indent(4).c_str());
while ( 1 ) { while ( 1 ) {
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
if (FAILED(pEnum->Next( 1, &pSymbol, &celt ))) { if (pEnum->Next( 1, &pSymbol, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -206,27 +206,29 @@ void iterateClasses(PDBApiContext& ctx) {
printf("%S</classes>\n", indent(4).c_str()); printf("%S</classes>\n", indent(4).c_str());
} }
// This method still leaks memory--seemingly in the pEnum->Next() for
// certain symbol types (e.g., tag == 32 (inline))
void dumpFunctionStackVariables( PDBApiContext& ctx, DWORD rva ) void dumpFunctionStackVariables( PDBApiContext& ctx, DWORD rva )
{ {
CComPtr<IDiaSymbol> pBlock; CComPtr<IDiaSymbol> pBlock;
if ( FAILED(ctx.Session().findSymbolByRVA( rva, SymTagBlock, &pBlock ) ) ) { if ( FAILED(ctx.Session().findSymbolByRVA( rva, SymTagBlock, &pBlock ) ) ) {
fatal( "Failed to find symbols by RVA" ); fatal( "Failed to find symbols by RVA" );
} }
for ( ; pBlock != NULL; ) { for ( ; pBlock != NULL; ) {
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
// Local data search // Local data search
if ( FAILED( pBlock->findChildren( SymTagNull, NULL, nsNone, &pEnum ) ) ) { if ( FAILED( pBlock->findChildren( SymTagNull, NULL, nsNone, &pEnum ) ) ) {
fatal( "Local scope findChildren failed" ); fatal( "Local scope findChildren failed" );
} }
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
DWORD tag; DWORD tag;
DWORD celt; DWORD celt;
while ( pEnum != NULL && SUCCEEDED( pEnum->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) { while (pEnum != NULL && pEnum->Next(1, &pSymbol, &celt) == S_OK && celt == 1) {
pSymbol->get_symTag( &tag ); pSymbol->get_symTag( &tag );
if ( tag == SymTagData ) { if ( tag == SymTagData ) {
printf("%S<stack_variable name=\"%S\" kind=\"%S\" offset=\"0x%x\" datatype=\"%S\" length=\"0x%I64x\" />\n", printf("%S<stack_variable name=\"%S\" kind=\"%S\" offset=\"0x%x\" datatype=\"%S\" length=\"0x%I64x\" />\n",
indent(12).c_str(), indent(12).c_str(),
getName(*pSymbol).c_str(), getName(*pSymbol).c_str(),
getKindAsString(*pSymbol).c_str(), getKindAsString(*pSymbol).c_str(),
getOffset(*pSymbol), getOffset(*pSymbol),
getTypeAsString(*pSymbol).c_str(), getTypeAsString(*pSymbol).c_str(),
@ -241,7 +243,7 @@ void dumpFunctionStackVariables( PDBApiContext& ctx, DWORD rva )
fatal( "Annotation findChildren failed" ); fatal( "Annotation findChildren failed" );
} }
pSymbol = NULL; pSymbol = NULL;
while ( pValues != NULL && SUCCEEDED( pValues->Next( 1, &pSymbol, &celt ) ) && celt == 1 ) { while ( pValues != NULL && pValues->Next( 1, &pSymbol, &celt ) == S_OK && celt == 1 ) {
//TODO //TODO
//CComVariant value; //CComVariant value;
//if ( pSymbol->get_value( &value ) != S_OK ) { //if ( pSymbol->get_value( &value ) != S_OK ) {
@ -259,53 +261,52 @@ void dumpFunctionStackVariables( PDBApiContext& ctx, DWORD rva )
break; break;
} }
// Move to lexical parent. // Move to lexical parent.
CComPtr<IDiaSymbol> pParent; CComPtr<IDiaSymbol> pParent;
if ( SUCCEEDED( pBlock->get_lexicalParent( &pParent ) ) && pParent != NULL ) { if ( pBlock->get_lexicalParent( &pParent ) == S_OK ) {
pBlock = pParent; pBlock = pParent;
} }
else { else {
break;
//fatal( "Finding lexical parent failed." ); //fatal( "Finding lexical parent failed." );
} }
}; };
} }
void dumpFunctionLines( IDiaSymbol& pSymbol, IDiaSession& pSession ) void dumpFunctionLines( IDiaSymbol& symbol, IDiaSession& session )
{ {
ULONGLONG length = 0; ULONGLONG length = 0;
DWORD isect = 0; DWORD isect = 0;
DWORD offset = 0; DWORD offset = 0;
pSymbol.get_addressSection( &isect ); symbol.get_addressSection( &isect );
pSymbol.get_addressOffset( &offset ); symbol.get_addressOffset( &offset );
pSymbol.get_length( &length ); symbol.get_length( &length );
if ( isect == 0 || length <= 0 ) { if ( isect == 0 || length <= 0 ) {
return; return;
} }
CComPtr<IDiaEnumLineNumbers> pLines; CComPtr<IDiaEnumLineNumbers> pLines;
if (FAILED(pSession.findLinesByAddr( isect, offset, static_cast<DWORD>( length ), &pLines ))) { if (session.findLinesByAddr( isect, offset, static_cast<DWORD>( length ), &pLines ) != S_OK ) {
return; return;
} }
DWORD celt = 0; DWORD celt = 0;
while ( 1 ) { while ( 1 ) {
CComPtr<IDiaLineNumber> pLine; CComPtr<IDiaLineNumber> pLine;
if (FAILED(pLines->Next( 1, &pLine, &celt ))) { if (pLines->Next( 1, &pLine, &celt ) != S_OK) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
break; break;
} }
CComPtr<IDiaSymbol> pComp; CComPtr<IDiaSymbol> pComp;
pLine->get_compiland( &pComp ); pLine->get_compiland( &pComp );
CComPtr<IDiaSourceFile> pSrc; CComPtr<IDiaSourceFile> pSrc;
pLine->get_sourceFile( &pSrc ); pLine->get_sourceFile( &pSrc );
BSTR temp = NULL;
pSrc->get_fileName(&temp);
bstr_t sourceFileName; bstr_t sourceFileName;
sourceFileName.Attach(temp); pSrc->get_fileName(sourceFileName.GetAddress());
DWORD addr = 0; DWORD addr = 0;
pLine->get_relativeVirtualAddress( &addr ); pLine->get_relativeVirtualAddress( &addr );
@ -315,22 +316,22 @@ void dumpFunctionLines( IDiaSymbol& pSymbol, IDiaSession& pSession )
DWORD end = 0; DWORD end = 0;
pLine->get_lineNumberEnd( &end ); pLine->get_lineNumberEnd( &end );
printf("%S<line_number source_file=\"%S\" start=\"0x%x\" end=\"0x%x\" addr=\"0x%x\" /> \n", printf("%S<line_number source_file=\"%ws\" start=\"0x%x\" end=\"0x%x\" addr=\"0x%x\" /> \n",
indent(12).c_str(), sourceFileName.GetBSTR(), start, end, addr); indent(12).c_str(), sourceFileName.GetBSTR(), start, end, addr);
} }
} }
void iterateFunctions(PDBApiContext& ctx) { void iterateFunctions(PDBApiContext& ctx) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumSymbols> pEnum; CComPtr<IDiaEnumSymbols> pEnum;
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
ctx.Global().findChildren(SymTagFunction, NULL, nsNone, &pEnum); ctx.Global().findChildren(SymTagFunction, NULL, nsNone, &pEnum);
if (pEnum == NULL) { if (pEnum == NULL) {
return; return;
} }
printf("%S<functions>\n", indent(4).c_str()); printf("%S<functions>\n", indent(4).c_str());
while ( 1 ) { while ( 1 ) {
if (FAILED(pEnum->Next( 1, &pSymbol, &celt ))) { if (pEnum->Next( 1, &pSymbol, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -339,10 +340,11 @@ void iterateFunctions(PDBApiContext& ctx) {
const DWORD tag = getTag(*pSymbol); const DWORD tag = getTag(*pSymbol);
if (tag != SymTagFunction) {//do not delete if (tag != SymTagFunction) {//do not delete
pSymbol = 0;
continue; continue;
} }
const DWORD address = getRVA(*pSymbol); const DWORD address = getRVA(*pSymbol);
printf("%S<function name=\"%S\" address=\"0x%x\" length=\"0x%I64x\">\n", indent(8).c_str(), findMangledName(ctx, *pSymbol).c_str(), address, getLength(*pSymbol)); printf("%S<function name=\"%S\" address=\"0x%x\" length=\"0x%I64x\">\n", indent(8).c_str(), findMangledName(ctx, *pSymbol).c_str(), address, getLength(*pSymbol));
@ -360,7 +362,7 @@ void iterateSymbolTable(IDiaEnumSymbols * pSymbols) {
DWORD celt = 0; DWORD celt = 0;
while ( 1 ) { while ( 1 ) {
CComPtr<IDiaSymbol> pSymbol; CComPtr<IDiaSymbol> pSymbol;
if (FAILED(pSymbols->Next( 1, &pSymbol, &celt ))) { if (pSymbols->Next( 1, &pSymbol, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -378,7 +380,7 @@ void iterateSymbolTable(IDiaEnumSymbols * pSymbols) {
printf("tag=\"%S\" ", getTagAsString(*pSymbol).c_str()); printf("tag=\"%S\" ", getTagAsString(*pSymbol).c_str());
printf("kind=\"%S\" ", getKindAsString(*pSymbol).c_str()); printf("kind=\"%S\" ", getKindAsString(*pSymbol).c_str());
printf("index=\"0x%x\" ", getIndex(*pSymbol)); printf("index=\"0x%x\" ", getIndex(*pSymbol));
printf("undecorated=\"%ws\" ", getUndecoratedName(*pSymbol).c_str()); printf("undecorated=\"%S\" ", getUndecoratedName(*pSymbol).c_str());
printf("value=\"%S\" ", getValue(*pSymbol).c_str()); printf("value=\"%S\" ", getValue(*pSymbol).c_str());
printf("datatype=\"%S\" ", getTypeAsString(*pSymbol).c_str()); printf("datatype=\"%S\" ", getTypeAsString(*pSymbol).c_str());
printf(" />\n"); printf(" />\n");
@ -386,17 +388,12 @@ void iterateSymbolTable(IDiaEnumSymbols * pSymbols) {
} }
void iterateSourceFiles(IDiaEnumSourceFiles * pSourceFiles) { void iterateSourceFiles(IDiaEnumSourceFiles * pSourceFiles) {
HRESULT hr = S_OK;
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaSourceFile> pSourceFile; CComPtr<IDiaSourceFile> pSourceFile;
while ( SUCCEEDED( hr = pSourceFiles->Next( 1, &pSourceFile, &celt ) ) && celt == 1 ) { while ( pSourceFiles->Next( 1, &pSourceFile, &celt ) == S_OK && celt == 1 ) {
BSTR temp = NULL;
pSourceFile->get_fileName( &temp );
bstr_t name; bstr_t name;
name.Attach(temp);
DWORD id = 0; DWORD id = 0;
pSourceFile->get_uniqueId( &id ); if( (pSourceFile->get_fileName( name.GetAddress() ) == S_OK) && (pSourceFile->get_uniqueId( &id ) == S_OK) ) {
if ( name.GetAddress() != NULL ) {
printf("%S<source_file name=\"%ws\" id=\"0x%x\" /> \n", indent(12).c_str(), name.GetBSTR(), id); printf("%S<source_file name=\"%ws\" id=\"0x%x\" /> \n", indent(12).c_str(), name.GetBSTR(), id);
} }
pSourceFile = NULL; pSourceFile = NULL;
@ -411,10 +408,9 @@ void iterateSourceFiles(IDiaEnumSourceFiles * pSourceFiles) {
* information in the segment map. * information in the segment map.
*/ */
void iterateSegments(IDiaEnumSegments * pSegments) { void iterateSegments(IDiaEnumSegments * pSegments) {
HRESULT hr = S_OK;
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaSegment> pSegment; CComPtr<IDiaSegment> pSegment;
while ( SUCCEEDED( hr = pSegments->Next( 1, &pSegment, &celt ) ) && celt == 1 ) { while ( pSegments->Next( 1, &pSegment, &celt ) == S_OK && celt == 1 ) {
DWORD rva = 0; DWORD rva = 0;
DWORD seg = 0; DWORD seg = 0;
pSegment->get_addressSection( &seg ); pSegment->get_addressSection( &seg );
@ -429,21 +425,21 @@ void iterateSegments(IDiaEnumSegments * pSegments) {
* that is, a contiguous block of memory contributed * that is, a contiguous block of memory contributed
* to the image by a compiland. * to the image by a compiland.
*/ */
void iterateSections(PDBApiContext& ctx, IDiaEnumSectionContribs& pSecContribs) { void iterateSections(PDBApiContext& ctx, IDiaEnumSectionContribs& secContribs) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaSymbol> pSym ; CComPtr<IDiaSymbol> pSym ;
CComPtr<IDiaSectionContrib> pSecContrib; CComPtr<IDiaSectionContrib> pSecContrib;
while ( 1 ) { while ( 1 ) {
if (pSecContribs.Next( 1, &pSecContrib, &celt ) < 0 ) { if (secContribs.Next( 1, &pSecContrib, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
break; break;
} }
DWORD rva = 0; DWORD rva = 0;
if (SUCCEEDED(pSecContrib->get_relativeVirtualAddress( &rva ))) { if (pSecContrib->get_relativeVirtualAddress( &rva ) == S_OK) {
if (FAILED(ctx.Session().findSymbolByRVA( rva, SymTagNull, &pSym )) ) { if (ctx.Session().findSymbolByRVA( rva, SymTagNull, &pSym ) != S_OK ) {
pSym = NULL; pSym = NULL;
} }
} }
@ -453,7 +449,7 @@ void iterateSections(PDBApiContext& ctx, IDiaEnumSectionContribs& pSecContribs)
pSecContrib->get_addressSection( &isect ); pSecContrib->get_addressSection( &isect );
pSecContrib->get_addressOffset( &offset ); pSecContrib->get_addressOffset( &offset );
pSecContrib = NULL; pSecContrib = NULL;
if (FAILED(ctx.Session().findSymbolByAddr( isect, offset, SymTagNull, &pSym )) ) { if (ctx.Session().findSymbolByAddr( isect, offset, SymTagNull, &pSym ) != S_OK ) {
pSym = NULL; pSym = NULL;
} }
} }
@ -475,26 +471,21 @@ void iterateSections(PDBApiContext& ctx, IDiaEnumSectionContribs& pSecContribs)
*/ */
void iterateInjectedSource(IDiaEnumInjectedSources * pInjectedSrcs) { void iterateInjectedSource(IDiaEnumInjectedSources * pInjectedSrcs) {
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaInjectedSource> pInjectedSrc; CComPtr<IDiaInjectedSource> pInjectedSrc;
while ( 1 ) { while ( 1 ) {
const HRESULT hr = pInjectedSrcs->Next( 1, &pInjectedSrc, &celt ); if (pInjectedSrcs->Next( 1, &pInjectedSrc, &celt ) != S_OK ) {
if (FAILED(hr)) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
break; break;
} }
BSTR fileNameTemp = NULL;
pInjectedSrc->get_filename(&fileNameTemp);
bstr_t filename; bstr_t filename;
filename.Attach(fileNameTemp); pInjectedSrc->get_filename(filename.GetAddress());
BSTR objectNameTemp = NULL;
pInjectedSrc->get_objectFilename(&objectNameTemp);
bstr_t objectname; bstr_t objectname;
objectname.Attach(objectNameTemp); pInjectedSrc->get_objectFilename(objectname.GetAddress());
DWORD crc; DWORD crc;
pInjectedSrc->get_crc(&crc); pInjectedSrc->get_crc(&crc);
@ -508,6 +499,8 @@ void iterateInjectedSource(IDiaEnumInjectedSources * pInjectedSrcs) {
objectname.GetBSTR(), objectname.GetBSTR(),
crc, crc,
length); length);
pInjectedSrc = NULL;
} }
} }
@ -521,8 +514,7 @@ void iterateFrameData(IDiaEnumFrameData * pEnumFrameData) {
while ( 1 ) { while ( 1 ) {
CComPtr<IDiaFrameData> pFrameData; CComPtr<IDiaFrameData> pFrameData;
const HRESULT hr = pEnumFrameData->Next( 1, &pFrameData, &celt ); if (pEnumFrameData->Next( 1, &pFrameData, &celt ) != S_OK) {
if (FAILED(hr)) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
@ -532,66 +524,59 @@ void iterateFrameData(IDiaEnumFrameData * pEnumFrameData) {
} }
} }
int iterateTables(PDBApiContext& ctx, bool printAll) { void iterateTables(PDBApiContext& ctx, bool printAll) {
printf("%S<tables>\n", indent(4).c_str()); printf("%S<tables>\n", indent(4).c_str());
HRESULT hr = S_OK;
DWORD celt = 0; DWORD celt = 0;
CComPtr<IDiaEnumTables> pTables; CComPtr<IDiaEnumTables> pTables;
hr = ctx.Session().getEnumTables( &pTables ); if ( ctx.Session().getEnumTables( &pTables ) != S_OK ) {
if ( FAILED(hr) ) { return;
return hr;
} }
while ( 1 ) { while ( 1 ) {
CComPtr<IDiaTable> pTable; CComPtr<IDiaTable> pTable;
if (FAILED(pTables->Next( 1, &pTable, &celt ))) { if (pTables->Next( 1, &pTable, &celt ) != S_OK ) {
break; break;
} }
if (celt != 1) { if (celt != 1) {
break; break;
} }
BSTR nameTemp;
pTable->get_name( &nameTemp );
bstr_t name; bstr_t name;
name.Attach(nameTemp); pTable->get_name( name.GetAddress() );
printf("%S<table name=\"%ws\">\n", indent(8).c_str(), name.GetBSTR() ); printf("%S<table name=\"%ws\">\n", indent(8).c_str(), name.GetBSTR() );
CComPtr<IDiaEnumSymbols> pSymbols; CComPtr<IDiaEnumSymbols> pSymbols;
CComPtr<IDiaEnumSourceFiles> pSourceFiles; CComPtr<IDiaEnumSourceFiles> pSourceFiles;
CComPtr<IDiaEnumSegments> pSegments; CComPtr<IDiaEnumSegments> pSegments;
CComPtr<IDiaEnumSectionContribs> pSecContribs; CComPtr<IDiaEnumSectionContribs> pSecContribs;
CComPtr<IDiaEnumInjectedSources> pInjectedSrcs; CComPtr<IDiaEnumInjectedSources> pInjectedSrcs;
CComPtr<IDiaEnumFrameData> pEnumFrameData; CComPtr<IDiaEnumFrameData> pEnumFrameData;
if ( SUCCEEDED( pTable->QueryInterface(IID_PPV_ARGS(&pSymbols) ) ) ) { if ( pTable->QueryInterface(IID_PPV_ARGS(&pSymbols) ) == S_OK ) {
iterateSymbolTable(pSymbols); iterateSymbolTable(pSymbols);
} }
else if ( SUCCEEDED( pTable->QueryInterface(IID_PPV_ARGS(&pSourceFiles) ) ) ) { else if ( pTable->QueryInterface(IID_PPV_ARGS(&pSourceFiles) ) == S_OK ) {
iterateSourceFiles(pSourceFiles); iterateSourceFiles(pSourceFiles);
} }
else if ( SUCCEEDED( pTable->QueryInterface(IID_PPV_ARGS(&pSegments)) ) ) { else if ( pTable->QueryInterface(IID_PPV_ARGS(&pSegments)) == S_OK ) {
iterateSegments(pSegments); iterateSegments(pSegments);
} }
else if ( SUCCEEDED( pTable->QueryInterface(IID_PPV_ARGS(&pSecContribs) ) ) ) { else if ( pTable->QueryInterface(IID_PPV_ARGS(&pSecContribs) ) == S_OK ) {
if (printAll) { if (printAll) {
iterateSections(ctx, *pSecContribs); iterateSections(ctx, *pSecContribs);
} }
} }
else if ( SUCCEEDED( pTable->QueryInterface(IID_PPV_ARGS(&pInjectedSrcs) ) ) ) { else if ( pTable->QueryInterface(IID_PPV_ARGS(&pInjectedSrcs) ) == S_OK ) {
iterateInjectedSource(pInjectedSrcs); iterateInjectedSource(pInjectedSrcs);
} }
else if ( SUCCEEDED( pTable->QueryInterface(IID_PPV_ARGS(&pEnumFrameData) ) ) ) { else if ( pTable->QueryInterface(IID_PPV_ARGS(&pEnumFrameData) ) == S_OK ) {
iterateFrameData(pEnumFrameData); iterateFrameData(pEnumFrameData);
} }
printf("%S</table>\n", indent(8).c_str()); printf("%S</table>\n", indent(8).c_str());
} }
printf("%S</tables>\n", indent(4).c_str()); printf("%S</tables>\n", indent(4).c_str());
return 0;
} }

View file

@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include "pdb.h" #include "pdb.h"
#include "iterate.h" #include "iterate.h"
#include <signal.h> #include <signal.h>
@ -23,8 +22,8 @@ void segvHandler(int /*sig*/) {
exit(1); // Just die - prevents OS from popping-up a dialog exit(1); // Just die - prevents OS from popping-up a dialog
} }
int wmain(int argc, wchar_t ** argv) { void doAllWork(int argc, wchar_t ** argv) {
if ( (argc < 2) || (argc > 5) ) { if ((argc < 2) || (argc > 5)) {
printf("USAGE:\n"); printf("USAGE:\n");
printf("\tValidation: %S <input pdb file> <guid OR signature> <age> [-fulloutput]\n", argv[0]); printf("\tValidation: %S <input pdb file> <guid OR signature> <age> [-fulloutput]\n", argv[0]);
printf("\tNo Validation: %S <input pdb file> [-fulloutput]\n", argv[0]); printf("\tNo Validation: %S <input pdb file> [-fulloutput]\n", argv[0]);
@ -43,23 +42,28 @@ int wmain(int argc, wchar_t ** argv) {
std::unique_ptr<PDBApiContext> pbdApiContext; std::unique_ptr<PDBApiContext> pbdApiContext;
if (argc <= 3) { // argc is either 2 or 3 if (argc <= 3) { // argc is either 2 or 3
if ( (argc == 3) && (wcscmp(argv[2], L"-fulloutput") == 0) ) { if ((argc == 3) && (wcscmp(argv[2], L"-fulloutput") == 0)) {
doPrintAll = true; doPrintAll = true;
} }
pbdApiContext = std::make_unique<PDBApiContext>(std::wstring(argv[1]), L"", L""); pbdApiContext = std::make_unique<PDBApiContext>(std::wstring(argv[1]), L"", L"");
} else { // argc is either 4 or 5 }
if ( (argc == 5) && (wcscmp(argv[4], L"-fulloutput") == 0) ) { else { // argc is either 4 or 5
if ((argc == 5) && (wcscmp(argv[4], L"-fulloutput") == 0)) {
doPrintAll = true; doPrintAll = true;
} }
pbdApiContext = std::make_unique<PDBApiContext>(std::wstring(argv[1]), std::wstring(argv[2]), std::wstring(argv[3])); pbdApiContext = std::make_unique<PDBApiContext>(std::wstring(argv[1]), std::wstring(argv[2]), std::wstring(argv[3]));
} }
iterateEnums(*pbdApiContext); iterateEnums(*pbdApiContext);
iterateDataTypes(*pbdApiContext); iterateDataTypes(*pbdApiContext);
iterateTypedefs(*pbdApiContext); iterateTypedefs(*pbdApiContext);
iterateClasses(*pbdApiContext); iterateClasses(*pbdApiContext);
iterateFunctions(*pbdApiContext); iterateFunctions(*pbdApiContext); // still leaks
iterateTables(*pbdApiContext, doPrintAll); iterateTables(*pbdApiContext, doPrintAll); // still leaks.
}
int wmain(int argc, wchar_t ** argv) {
// Doing work in separate method so that we can do memory snapshot profiling in main
// before and after the call to doAllWork().
doAllWork(argc, argv);
return 0; return 0;
} }

View file

@ -78,10 +78,10 @@ int PDBApiContext::init(const std::wstring& szFilename, const std::wstring& szSi
} }
checkErr(hr); checkErr(hr);
if (FAILED(pSource->openSession( &pSession ))) { if (pSource->openSession( &pSession ) != S_OK) {
fatal("Unable to open session\n"); fatal("Unable to open session\n");
} }
if (FAILED(pSession->get_globalScope( &pGlobal ))) { if (pSession->get_globalScope( &pGlobal ) != S_OK) {
fatal("Unable to get global scope\n"); fatal("Unable to get global scope\n");
} }
@ -99,12 +99,12 @@ int PDBApiContext::init(const std::wstring& szFilename, const std::wstring& szSi
int maxGUIDStrLen = 64; int maxGUIDStrLen = 64;
std::wstring guidStr(maxGUIDStrLen, L'\0'); std::wstring guidStr(maxGUIDStrLen, L'\0');
if (SUCCEEDED(pGlobal->get_guid( &currGUID ))) { if (pGlobal->get_guid( &currGUID ) == S_OK) {
if (StringFromGUID2(currGUID, &guidStr[0], maxGUIDStrLen) <= 0) { if (StringFromGUID2(currGUID, &guidStr[0], maxGUIDStrLen) <= 0) {
fatal("Unable to convert GUID\n"); fatal("Unable to convert GUID\n");
} }
if (FAILED(pGlobal->get_age( &currAge ))) { if (pGlobal->get_age( &currAge ) != S_OK) {
fatal("Unable to get PDB age\n"); fatal("Unable to get PDB age\n");
} }
} else { } else {

View file

@ -37,8 +37,8 @@ std::wstring printVariant( VARIANT & v ) {
return L"null"; return L"null";
} }
const int blen = 100; const int blen = 100;
wchar_t variant[blen] = {}; wchar_t variant[blen] = {};
switch( v.vt ) { switch( v.vt ) {
case VT_ARRAY://Indicates a SAFEARRAY pointer. case VT_ARRAY://Indicates a SAFEARRAY pointer.
swprintf_s(variant, blen, L"%I64d", (ULONGLONG) v.parray);//TODO swprintf_s(variant, blen, L"%I64d", (ULONGLONG) v.parray);//TODO
@ -106,22 +106,20 @@ std::wstring printVariant( VARIANT & v ) {
} }
} }
void printBound( IDiaSymbol& pBound ) { void printBound( IDiaSymbol& bound ) {
DWORD tag = 0; DWORD tag = 0;
BSTR nameTemp = NULL;
DWORD kind = 0; DWORD kind = 0;
pBound.get_symTag( &tag ); bound.get_symTag( &tag );
pBound.get_locationType( &kind ); bound.get_locationType( &kind );
bstr_t name;
if ( tag == SymTagData && kind == LocIsConstant ) { if ( tag == SymTagData && kind == LocIsConstant ) {
//TODO //TODO
//CComVariant v; //CComVariant v;
//pBound->get_value( &v ); //pBound->get_value( &v );
//printVariant( v ); //printVariant( v );
} }
else if ( pBound.get_name( &nameTemp ) == S_OK ) { else if ( bound.get_name( name.GetAddress()) == S_OK ) {
bstr_t name;
name.Attach(nameTemp);
printf( "%ws", name.GetBSTR() ); printf( "%ws", name.GetBSTR() );
} }
} }
@ -134,7 +132,7 @@ std::wstring printType( IDiaSymbol * pType, const std::wstring& suffix ) {
DWORD tag = getTag(*pType); DWORD tag = getTag(*pType);
if ( tag == SymTagPointerType ) { if ( tag == SymTagPointerType ) {
CComPtr<IDiaSymbol> pBaseType; CComPtr<IDiaSymbol> pBaseType;
if ( pType->get_type( &pBaseType ) == S_OK ) { if ( pType->get_type( &pBaseType ) == S_OK ) {
return printType(pBaseType, suffix + L" *"); return printType(pBaseType, suffix + L" *");
} }
@ -148,7 +146,7 @@ std::wstring printType( IDiaSymbol * pType, const std::wstring& suffix ) {
} }
if ( tag == SymTagArrayType ) { if ( tag == SymTagArrayType ) {
CComPtr<IDiaSymbol> pBaseType = getType( *pType ); CComPtr<IDiaSymbol> pBaseType = getType( *pType );
if ( pBaseType == NULL ) { if ( pBaseType == NULL ) {
return L""; return L"";
} }
@ -158,7 +156,7 @@ std::wstring printType( IDiaSymbol * pType, const std::wstring& suffix ) {
lenElem = lenArray; lenElem = lenArray;
} }
const size_t strLen = suffix.length() + 64 + 3; // length of suffix + wag_for_numeric_value + "[]\0" const size_t strLen = suffix.length() + 64 + 3; // length of suffix + wag_for_numeric_value + "[]\0"
std::vector<wchar_t> str(strLen); std::vector<wchar_t> str(strLen);
swprintf_s(str.data(), strLen, L"%s[%I64d]", suffix.c_str(), lenArray / lenElem); swprintf_s(str.data(), strLen, L"%s[%I64d]", suffix.c_str(), lenArray / lenElem);
return printType(pBaseType, str.data()); return printType(pBaseType, str.data());
} }
@ -170,27 +168,27 @@ std::wstring printType( IDiaSymbol * pType, const std::wstring& suffix ) {
if ( tag == SymTagCustomType ) { if ( tag == SymTagCustomType ) {
DWORD id = 0; DWORD id = 0;
DWORD rec = 0; DWORD rec = 0;
GUID guid = GUID_NULL; GUID guid = GUID_NULL;
if (pType->get_guid(&guid) == S_OK) { if ( pType->get_guid(&guid) == S_OK ) {
const int maxGUIDStrLen = 64 + 1; const int maxGUIDStrLen = 64 + 1;
std::vector<wchar_t> guidStr(maxGUIDStrLen); std::vector<wchar_t> guidStr(maxGUIDStrLen);
if (StringFromGUID2(guid, guidStr.data(), maxGUIDStrLen) > 0) { if (StringFromGUID2(guid, guidStr.data(), maxGUIDStrLen) > 0) {
return guidStr.data(); return guidStr.data();
} }
} }
else if ( pType->get_oemId( &id ) == S_OK && pType->get_oemSymbolId( &rec ) == S_OK ) { else if ( pType->get_oemId( &id ) == S_OK && pType->get_oemSymbolId( &rec ) == S_OK ) {
const size_t strLen = 256; // wag_for_2_hex_numbers "0xNNNNN:0xNNNNN" const size_t strLen = 256; // wag_for_2_hex_numbers "0xNNNNN:0xNNNNN"
wchar_t str[strLen] = {}; wchar_t str[strLen] = {};
if (str != NULL) { if (str != NULL) {
swprintf_s(str, L"0x%x:0x%x", id, rec); swprintf_s(str, L"0x%x:0x%x", id, rec);
return str; return str;
} }
} }
return L""; return L"";
} }
if ( !name.empty() ) { if ( !name.empty() ) {
return name + suffix; return name + suffix;
} }
return L"Undefined"; return L"Undefined";
@ -200,14 +198,14 @@ void printScopeName( IDiaSymbol& pscope ) {
printf("<scope name=\"%S\" tag=\"%S\" />\n", getName( pscope ).c_str(), getTagAsString( pscope ).c_str()); printf("<scope name=\"%S\" tag=\"%S\" />\n", getName( pscope ).c_str(), getTagAsString( pscope ).c_str());
} }
void printNameFromScope( IDiaSymbol& pscope, IDiaEnumSymbols& pEnum ) { void printNameFromScope( IDiaSymbol& scope, IDiaEnumSymbols& myEnum ) {
CComPtr<IDiaSymbol> pSym; CComPtr<IDiaSymbol> pSym;
DWORD celt = 0; DWORD celt = 0;
while ( SUCCEEDED( pEnum.Next( 1, &pSym, &celt ) ) && celt == 1 ) { while ( myEnum.Next( 1, &pSym, &celt ) == S_OK && celt == 1 ) {
wprintf( L"\t%s %s found in ", getTagAsString(*pSym).c_str(), getName(*pSym).c_str() ); printf( "\t%S %S found in ", getTagAsString(*pSym).c_str(), getName(*pSym).c_str() );
printScopeName( pscope ); printScopeName( scope );
wprintf( L"\n" ); printf( "\n" );
pSym = 0; pSym = 0;
} }
} }

View file

@ -54,19 +54,19 @@ const static std::wstring SYMBOL_TAG_STRINGS [] = {
L"Thunk", L"Thunk",
L"CustomType", L"CustomType",
L"ManagedType", L"ManagedType",
L"Dimension", L"Dimension",
L"CallSite", L"CallSite",
L"InlineSite", L"InlineSite",
L"BaseInterface", L"BaseInterface",
L"VectorType", L"VectorType",
L"MatrixType", L"MatrixType",
L"HLSLType", L"HLSLType",
L"Caller", L"Caller",
L"Callee", L"Callee",
L"Export", L"Export",
L"HeapAllocationSite", L"HeapAllocationSite",
L"CoffGroup", L"CoffGroup",
L"Inlinee", L"Inlinee",
L"" L""
}; };
@ -174,11 +174,9 @@ const static std::wstring BASIC_TYPE_STRINGS [] = {
L"char32_t" L"char32_t"
}; };
std::wstring getName(IDiaSymbol& pSymbol) { std::wstring getName(IDiaSymbol& symbol) {
BSTR temp = NULL; bstr_t name;
if (SUCCEEDED(pSymbol.get_name(&temp))) { if (symbol.get_name(name.GetAddress()) == S_OK) {
bstr_t name;
name.Attach(temp);
const std::wstring wstrName = std::wstring(name.GetBSTR(), name.length()); const std::wstring wstrName = std::wstring(name.GetBSTR(), name.length());
if (wstrName.empty()) { if (wstrName.empty()) {
return escapeXmlEntities(L"NONAME"); return escapeXmlEntities(L"NONAME");
@ -186,20 +184,20 @@ std::wstring getName(IDiaSymbol& pSymbol) {
if (wstrName.find(L"unnamed-tag") != std::wstring::npos) { if (wstrName.find(L"unnamed-tag") != std::wstring::npos) {
DWORD symIndexId = 0; DWORD symIndexId = 0;
if (FAILED(pSymbol.get_symIndexId(&symIndexId))) { if (symbol.get_symIndexId(&symIndexId) != S_OK) {
symIndexId = 0; symIndexId = 0;
} }
const size_t length = 20; // length of: "<unnamed_NNNN>\0" + 1 extra const size_t length = 20; // length of: "<unnamed_NNNN>\0" + 1 extra
std::vector<wchar_t> str(20); std::vector<wchar_t> str(length);
swprintf_s(str.data(), length, L"<unnamed_%04x>", symIndexId); swprintf_s(str.data(), length, L"<unnamed_%04x>", symIndexId);
return escapeXmlEntities(str.data()); return escapeXmlEntities(str.data());
} }
DWORD locType = 0; DWORD locType = 0;
ULONGLONG len = 0; ULONGLONG len = 0;
if (SUCCEEDED(pSymbol.get_locationType(&locType)) && if (symbol.get_locationType(&locType) == S_OK &&
locType == LocIsBitField && locType == LocIsBitField &&
SUCCEEDED(pSymbol.get_length(&len))) { symbol.get_length(&len) == S_OK) {
const size_t length = wstrName.length() + 4 + 32; // length of: name + ":0x\0" + wag_hex_numeric_str_len const size_t length = wstrName.length() + 4 + 32; // length of: name + ":0x\0" + wag_hex_numeric_str_len
std::vector<wchar_t> str(length); std::vector<wchar_t> str(length);
swprintf_s(str.data(), length, L"%ws:0x%I64x", wstrName.c_str(), len); swprintf_s(str.data(), length, L"%ws:0x%I64x", wstrName.c_str(), len);
@ -211,89 +209,87 @@ std::wstring getName(IDiaSymbol& pSymbol) {
return std::wstring(); return std::wstring();
} }
std::wstring getUndecoratedName(IDiaSymbol& pSymbol) { std::wstring getUndecoratedName(IDiaSymbol& symbol) {
BSTR temp = NULL; bstr_t name;
if (pSymbol.get_undecoratedName(&temp) == S_OK) { if (symbol.get_undecoratedName(name.GetAddress()) == S_OK) {
// May also return S_FALSE which is not failure, however in this case there is no name // May also return S_FALSE which is not failure, however in this case there is no name
bstr_t name;
name.Attach(temp);
return escapeXmlEntities(std::wstring(name.GetBSTR(), name.length())); return escapeXmlEntities(std::wstring(name.GetBSTR(), name.length()));
} }
return L""; return L"";
} }
DWORD getRVA(IDiaSymbol& pSymbol) { DWORD getRVA(IDiaSymbol& symbol) {
DWORD rva = 0; DWORD rva = 0;
pSymbol.get_relativeVirtualAddress( &rva ); symbol.get_relativeVirtualAddress( &rva );
return rva; return rva;
} }
ULONGLONG getLength(IDiaSymbol& pSymbol) { ULONGLONG getLength(IDiaSymbol& symbol) {
ULONGLONG len = 0; ULONGLONG len = 0;
pSymbol.get_length( &len ); symbol.get_length( &len );
return len; return len;
} }
DWORD getTag(IDiaSymbol& pSymbol) { DWORD getTag(IDiaSymbol& symbol) {
DWORD tag = 0; DWORD tag = 0;
pSymbol.get_symTag( &tag ); symbol.get_symTag( &tag );
return tag; return tag;
} }
std::wstring getTagAsString(IDiaSymbol& pSymbol) { std::wstring getTagAsString(IDiaSymbol& symbol) {
const DWORD tag = getTag(pSymbol); const DWORD tag = getTag(symbol);
if (tag > _countof(SYMBOL_TAG_STRINGS)) { if (tag > _countof(SYMBOL_TAG_STRINGS)) {
return L""; return L"";
} }
return SYMBOL_TAG_STRINGS[tag]; return SYMBOL_TAG_STRINGS[tag];
} }
DWORD getKind(IDiaSymbol& pSymbol) { DWORD getKind(IDiaSymbol& symbol) {
DWORD kind = 0; DWORD kind = 0;
pSymbol.get_dataKind( &kind ); symbol.get_dataKind( &kind );
return kind; return kind;
} }
DWORD getUdtKind(IDiaSymbol& pSymbol) { DWORD getUdtKind(IDiaSymbol& symbol) {
DWORD kind = 0; DWORD kind = 0;
pSymbol.get_udtKind( &kind ); symbol.get_udtKind( &kind );
return kind; return kind;
} }
std::wstring getKindAsString(IDiaSymbol& pSymbol) { std::wstring getKindAsString(IDiaSymbol& symbol) {
const DWORD tag = getTag(pSymbol); const DWORD tag = getTag(symbol);
if (tag == SymTagUDT) { if (tag == SymTagUDT) {
const DWORD kind = getUdtKind(pSymbol); const DWORD kind = getUdtKind(symbol);
if (kind < _countof(UDT_KIND_STRINGS)) { if (kind < _countof(UDT_KIND_STRINGS)) {
return UDT_KIND_STRINGS[kind]; return UDT_KIND_STRINGS[kind];
} }
return L""; return L"";
} }
const DWORD dataKind = getKind(pSymbol); const DWORD dataKind = getKind(symbol);
if (dataKind < _countof(DATA_KIND_STRINGS)) { if (dataKind < _countof(DATA_KIND_STRINGS)) {
return DATA_KIND_STRINGS[dataKind]; return DATA_KIND_STRINGS[dataKind];
} }
return L""; return L"";
} }
LONG getOffset(IDiaSymbol& pSymbol) { LONG getOffset(IDiaSymbol& symbol) {
LONG offset = 0; LONG offset = 0;
pSymbol.get_offset( &offset ); symbol.get_offset( &offset );
return offset; return offset;
} }
DWORD getIndex(IDiaSymbol& pSymbol) { DWORD getIndex(IDiaSymbol& symbol) {
DWORD index = 0; DWORD index = 0;
pSymbol.get_symIndexId( &index ); symbol.get_symIndexId( &index );
return index; return index;
} }
std::wstring getValue(IDiaSymbol& pSymbol) { std::wstring getValue(IDiaSymbol& symbol) {
if (getKind(pSymbol) == DataIsConstant) { if (getKind(symbol) == DataIsConstant) {
VARIANT value; VARIANT value;
HRESULT hr = pSymbol.get_value( &value ); value.vt = VT_EMPTY;
if (hr == S_OK) { if (symbol.get_value( &value ) == S_OK) {
return printVariant( value ); return printVariant( value );
} }
} }
return L""; return L"";
} }
/* /*
BSTR getBaseTypeName(IDiaSymbol * pSymbol) { BSTR getBaseTypeName(IDiaSymbol * symbol) {
IDiaSymbol * pBaseType; IDiaSymbol * pBaseType;
if (pType->get_type( &pBaseType ) != 0) { if (pType->get_type( &pBaseType ) != 0) {
return NULL; return NULL;
@ -310,17 +306,17 @@ BSTR getBaseTypeName(IDiaSymbol * pSymbol) {
} }
*/ */
CComPtr<IDiaSymbol> getType(IDiaSymbol& pSymbol) { CComPtr<IDiaSymbol> getType(IDiaSymbol& symbol) {
CComPtr<IDiaSymbol> pBaseType; CComPtr<IDiaSymbol> pBaseType;
if (SUCCEEDED(pSymbol.get_type( &pBaseType ))) { if (symbol.get_type( &pBaseType ) == S_OK) {
return pBaseType; return pBaseType;
} }
return NULL; return NULL;
} }
std::wstring getTypeAsString(IDiaSymbol& pSymbol) { std::wstring getTypeAsString(IDiaSymbol& symbol) {
std::wstring typeStr ; std::wstring typeStr ;
CComPtr<IDiaSymbol> pType; CComPtr<IDiaSymbol> pType;
if (SUCCEEDED(pSymbol.get_type( &pType ))) { if (symbol.get_type( &pType ) == S_OK) {
typeStr = printType( pType, L"" ); typeStr = printType( pType, L"" );
} }
else { else {
@ -329,20 +325,20 @@ std::wstring getTypeAsString(IDiaSymbol& pSymbol) {
return typeStr; return typeStr;
} }
static DWORD getBaseType(IDiaSymbol& pSymbol) { static DWORD getBaseType(IDiaSymbol& symbol) {
if (getTag(pSymbol) == SymTagBaseType) { if (getTag(symbol) == SymTagBaseType) {
DWORD baseType = btNoType; DWORD baseType = btNoType;
if (FAILED(pSymbol.get_baseType(&baseType))) { if (symbol.get_baseType(&baseType) != S_OK) {
return btNoType; return btNoType;
} }
return baseType; return baseType;
} }
return btNoType; return btNoType;
} }
std::wstring getBaseTypeAsString(IDiaSymbol& pSymbol) { std::wstring getBaseTypeAsString(IDiaSymbol& symbol) {
const ULONGLONG len = getLength(pSymbol); const ULONGLONG len = getLength(symbol);
const DWORD bt = getBaseType(pSymbol); const DWORD bt = getBaseType(symbol);
switch(bt) { switch(bt) {
case btInt: case btInt:
switch(len) { switch(len) {
case 1: return L"char"; case 1: return L"char";
@ -359,7 +355,7 @@ std::wstring getBaseTypeAsString(IDiaSymbol& pSymbol) {
case 8: return L"__uint64"; case 8: return L"__uint64";
} }
break; break;
case btFloat: case btFloat:
switch(len) { switch(len) {
case 4: return L"float"; case 4: return L"float";
case 8: return L"double"; case 8: return L"double";

View file

@ -23,6 +23,7 @@ std::wstring indent(size_t nSpaces) {
std::wstring escapeXmlEntities(const std::wstring& str) { std::wstring escapeXmlEntities(const std::wstring& str) {
std::wstring escaped; std::wstring escaped;
// Setting initial space; string operators will get more if needed.
escaped.reserve(str.length() * 2); escaped.reserve(str.length() * 2);
for (int i = 0 ; i < str.length(); ++i) { for (int i = 0 ; i < str.length(); ++i) {

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,6 +27,6 @@ void iterateEnums(PDBApiContext& ctx);
void iterateTypedefs(PDBApiContext& ctx); void iterateTypedefs(PDBApiContext& ctx);
void iterateClasses(PDBApiContext& ctx); void iterateClasses(PDBApiContext& ctx);
void iterateFunctions(PDBApiContext& ctx); void iterateFunctions(PDBApiContext& ctx);
int iterateTables(PDBApiContext& ctx, bool printAll); void iterateTables(PDBApiContext& ctx, bool printAll);
#endif #endif

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View file

@ -1,6 +1,5 @@
/* ### /* ###
* IP: GHIDRA * IP: GHIDRA
* REVIEWED: YES
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.