| Server IP : 121.121.20.254 / Your IP : 216.73.216.202 Web Server : Microsoft-IIS/10.0 System : Windows NT WEB-SERVER 10.0 build 20348 (Windows Server 2022) AMD64 User : IUSR ( 0) PHP Version : 8.3.28 Disable Function : NONE MySQL : ON | cURL : ON | WGET : OFF | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /Program Files (x86)/Microsoft Visual Studio/18/BuildTools/DIA SDK/Samples/DIA2Dump/ |
Upload File : |
// PrintSymbol.cpp : Defines the printing procedures for the symbols
//
// This is a part of the Debug Interface Access SDK
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is only intended as a supplement to the
// Debug Interface Access SDK and related electronic documentation
// provided with the library.
// See these sources for detailed information regarding the
// Debug Interface Access SDK API.
//
#include "stdafx.h"
#include <malloc.h>
#include "dia2.h"
#include "regs.h"
#include "PrintSymbol.h"
// Basic types
const wchar_t * const rgBaseType[] =
{
L"<NoType>", // btNoType = 0,
L"void", // btVoid = 1,
L"char", // btChar = 2,
L"wchar_t", // btWChar = 3,
L"signed char",
L"unsigned char",
L"int", // btInt = 6,
L"unsigned int", // btUInt = 7,
L"float", // btFloat = 8,
L"<BCD>", // btBCD = 9,
L"bool", // btBool = 10,
L"short",
L"unsigned short",
L"long", // btLong = 13,
L"unsigned long", // btULong = 14,
L"__int8",
L"__int16",
L"__int32",
L"__int64",
L"__int128",
L"unsigned __int8",
L"unsigned __int16",
L"unsigned __int32",
L"unsigned __int64",
L"unsigned __int128",
L"<currency>", // btCurrency = 25,
L"<date>", // btDate = 26,
L"VARIANT", // btVariant = 27,
L"<complex>", // btComplex = 28,
L"<bit>", // btBit = 29,
L"BSTR", // btBSTR = 30,
L"HRESULT", // btHresult = 31
L"char16_t", // btChar16 = 32
L"char32_t", // btChar32 = 33
L"char8_t", // btChar8 = 34
};
// Tags returned by Dia
const wchar_t * const rgTags[] =
{
L"(SymTagNull)", // SymTagNull
L"Executable (Global)", // SymTagExe
L"Compiland", // SymTagCompiland
L"CompilandDetails", // SymTagCompilandDetails
L"CompilandEnv", // SymTagCompilandEnv
L"Function", // SymTagFunction
L"Block", // SymTagBlock
L"Data", // SymTagData
L"Annotation", // SymTagAnnotation
L"Label", // SymTagLabel
L"PublicSymbol", // SymTagPublicSymbol
L"UserDefinedType", // SymTagUDT
L"Enum", // SymTagEnum
L"FunctionType", // SymTagFunctionType
L"PointerType", // SymTagPointerType
L"ArrayType", // SymTagArrayType
L"BaseType", // SymTagBaseType
L"Typedef", // SymTagTypedef
L"BaseClass", // SymTagBaseClass
L"Friend", // SymTagFriend
L"FunctionArgType", // SymTagFunctionArgType
L"FuncDebugStart", // SymTagFuncDebugStart
L"FuncDebugEnd", // SymTagFuncDebugEnd
L"UsingNamespace", // SymTagUsingNamespace
L"VTableShape", // SymTagVTableShape
L"VTable", // SymTagVTable
L"Custom", // SymTagCustom
L"Thunk", // SymTagThunk
L"CustomType", // SymTagCustomType
L"ManagedType", // SymTagManagedType
L"Dimension", // SymTagDimension
L"CallSite", // SymTagCallSite
L"InlineSite", // SymTagInlineSite
L"BaseInterface", // SymTagBaseInterface
L"VectorType", // SymTagVectorType
L"MatrixType", // SymTagMatrixType
L"HLSLType", // SymTagHLSLType
L"Caller", // SymTagCaller,
L"Callee", // SymTagCallee,
L"Export", // SymTagExport,
L"HeapAllocationSite", // SymTagHeapAllocationSite
L"CoffGroup", // SymTagCoffGroup
L"Inlinee", // SymTagInlinee
L"TaggedUnionCase", // SymTagTaggedUnionCase
};
// Processors
const wchar_t * const rgFloatPackageStrings[] =
{
L"hardware processor (80x87 for Intel processors)", // CV_CFL_NDP
L"emulator", // CV_CFL_EMU
L"altmath", // CV_CFL_ALT
L"???"
};
const wchar_t * const rgProcessorStrings[] =
{
L"8080", // CV_CFL_8080
L"8086", // CV_CFL_8086
L"80286", // CV_CFL_80286
L"80386", // CV_CFL_80386
L"80486", // CV_CFL_80486
L"Pentium", // CV_CFL_PENTIUM
L"Pentium Pro/Pentium II", // CV_CFL_PENTIUMII/CV_CFL_PENTIUMPRO
L"Pentium III", // CV_CFL_PENTIUMIII
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"MIPS (Generic)", // CV_CFL_MIPSR4000
L"MIPS16", // CV_CFL_MIPS16
L"MIPS32", // CV_CFL_MIPS32
L"MIPS64", // CV_CFL_MIPS64
L"MIPS I", // CV_CFL_MIPSI
L"MIPS II", // CV_CFL_MIPSII
L"MIPS III", // CV_CFL_MIPSIII
L"MIPS IV", // CV_CFL_MIPSIV
L"MIPS V", // CV_CFL_MIPSV
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"M68000", // CV_CFL_M68000
L"M68010", // CV_CFL_M68010
L"M68020", // CV_CFL_M68020
L"M68030", // CV_CFL_M68030
L"M68040", // CV_CFL_M68040
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"Alpha 21064", // CV_CFL_ALPHA, CV_CFL_ALPHA_21064
L"Alpha 21164", // CV_CFL_ALPHA_21164
L"Alpha 21164A", // CV_CFL_ALPHA_21164A
L"Alpha 21264", // CV_CFL_ALPHA_21264
L"Alpha 21364", // CV_CFL_ALPHA_21364
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"PPC 601", // CV_CFL_PPC601
L"PPC 603", // CV_CFL_PPC603
L"PPC 604", // CV_CFL_PPC604
L"PPC 620", // CV_CFL_PPC620
L"PPC w/FP", // CV_CFL_PPCFP
L"PPC (Big Endian)", // CV_CFL_PPCBE
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"SH3", // CV_CFL_SH3
L"SH3E", // CV_CFL_SH3E
L"SH3DSP", // CV_CFL_SH3DSP
L"SH4", // CV_CFL_SH4
L"SHmedia", // CV_CFL_SHMEDIA
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"ARM3", // CV_CFL_ARM3
L"ARM4", // CV_CFL_ARM4
L"ARM4T", // CV_CFL_ARM4T
L"ARM5", // CV_CFL_ARM5
L"ARM5T", // CV_CFL_ARM5T
L"ARM6", // CV_CFL_ARM6
L"ARM (XMAC)", // CV_CFL_ARM_XMAC
L"ARM (WMMX)", // CV_CFL_ARM_WMMX
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"Omni", // CV_CFL_OMNI
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"Itanium", // CV_CFL_IA64, CV_CFL_IA64_1
L"Itanium (McKinley)", // CV_CFL_IA64_2
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"CEE", // CV_CFL_CEE
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"AM33", // CV_CFL_AM33
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"M32R", // CV_CFL_M32R
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"TriCore", // CV_CFL_TRICORE
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"x64", // CV_CFL_X64
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"EBC", // CV_CFL_EBC
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"Thumb (CE)", // CV_CFL_THUMB
L"???",
L"???",
L"???",
L"ARM", // CV_CFL_ARMNT
L"???",
L"ARM64", // CV_CFL_ARM64
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"???",
L"UNKNOWN", // CV_CFL_UNKNOWN
L"D3D11_SHADE", // CV_CFL_D3D11_SHADER
};
const wchar_t * const rgDataKind[] =
{
L"Unknown",
L"Local",
L"Static Local",
L"Param",
L"Object Ptr",
L"File Static",
L"Global",
L"Member",
L"Static Member",
L"Constant",
};
const wchar_t * const rgUdtKind[] =
{
L"struct",
L"class",
L"union",
L"interface",
L"tagged union",
};
const wchar_t * const rgAccess[] =
{
L"", // No access specifier
L"private",
L"protected",
L"public"
};
const wchar_t * const rgCallingConvention[] =
{
L"CV_CALL_NEAR_C ",
L"CV_CALL_FAR_C ",
L"CV_CALL_NEAR_PASCAL ",
L"CV_CALL_FAR_PASCAL ",
L"CV_CALL_NEAR_FAST ",
L"CV_CALL_FAR_FAST ",
L"CV_CALL_SKIPPED ",
L"CV_CALL_NEAR_STD ",
L"CV_CALL_FAR_STD ",
L"CV_CALL_NEAR_SYS ",
L"CV_CALL_FAR_SYS ",
L"CV_CALL_THISCALL ",
L"CV_CALL_MIPSCALL ",
L"CV_CALL_GENERIC ",
L"CV_CALL_ALPHACALL ",
L"CV_CALL_PPCCALL ",
L"CV_CALL_SHCALL ",
L"CV_CALL_ARMCALL ",
L"CV_CALL_AM33CALL ",
L"CV_CALL_TRICALL ",
L"CV_CALL_SH5CALL ",
L"CV_CALL_M32RCALL ",
L"CV_ALWAYS_INLINED ",
L"CV_CALL_NEAR_VECTOR ",
L"CV_CALL_SWIFT ",
L"CV_CALL_RESERVED "
};
const wchar_t * const rgLanguage[] =
{
L"C", // CV_CFL_C
L"C++", // CV_CFL_CXX
L"FORTRAN", // CV_CFL_FORTRAN
L"MASM", // CV_CFL_MASM
L"Pascal", // CV_CFL_PASCAL
L"Basic", // CV_CFL_BASIC
L"COBOL", // CV_CFL_COBOL
L"LINK", // CV_CFL_LINK
L"CVTRES", // CV_CFL_CVTRES
L"CVTPGD", // CV_CFL_CVTPGD
L"C#", // CV_CFL_CSHARP
L"Visual Basic", // CV_CFL_VB
L"ILASM", // CV_CFL_ILASM
L"Java", // CV_CFL_JAVA
L"JScript", // CV_CFL_JSCRIPT
L"MSIL", // CV_CFL_MSIL
L"HLSL", // CV_CFL_HLSL
L"Objective-C", // CV_CFL_OBJC
L"Objective-C++", // CV_CFL_OBJCXX
L"Swift", // CV_CFL_SWIFT
L"ALIASOBJ", // CV_CFL_ALIASOBJ
L"Rust", // CV_CFL_RUST
L"Go", // CV_CFL_GO
};
const wchar_t * const rgLocationTypeString[] =
{
L"NULL",
L"static",
L"TLS",
L"RegRel",
L"ThisRel",
L"Enregistered",
L"BitField",
L"Slot",
L"IL Relative",
L"In MetaData",
L"Constant",
L"RegRelAliasIndir"
};
////////////////////////////////////////////////////////////
// Print a public symbol info: name, VA, RVA, SEG:OFF
//
void PrintPublicSymbol(IDiaSymbol *pSymbol)
{
DWORD dwSymTag;
DWORD dwRVA;
DWORD dwSeg;
DWORD dwOff;
BSTR bstrName;
if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
return;
}
if (pSymbol->get_relativeVirtualAddress(&dwRVA) != S_OK) {
dwRVA = 0xFFFFFFFF;
}
pSymbol->get_addressSection(&dwSeg);
pSymbol->get_addressOffset(&dwOff);
wprintf(L"%s: [%08X][%04X:%08X] ", rgTags[dwSymTag], dwRVA, dwSeg, dwOff);
if (dwSymTag == SymTagThunk) {
if (pSymbol->get_name(&bstrName) == S_OK) {
wprintf(L"%s\n", bstrName);
SysFreeString(bstrName);
}
else {
if (pSymbol->get_targetRelativeVirtualAddress(&dwRVA) != S_OK) {
dwRVA = 0xFFFFFFFF;
}
pSymbol->get_targetSection(&dwSeg);
pSymbol->get_targetOffset(&dwOff);
wprintf(L"target -> [%08X][%04X:%08X]\n", dwRVA, dwSeg, dwOff);
}
}
else {
// must be a function or a data symbol
BSTR bstrUndname;
if (pSymbol->get_name(&bstrName) == S_OK) {
if (pSymbol->get_undecoratedName(&bstrUndname) == S_OK) {
wprintf(L"%s(%s)\n", bstrName, bstrUndname);
SysFreeString(bstrUndname);
}
else {
wprintf(L"%s\n", bstrName);
}
SysFreeString(bstrName);
}
}
}
////////////////////////////////////////////////////////////
// Print a global symbol info: name, VA, RVA, SEG:OFF
//
void PrintGlobalSymbol(IDiaSymbol *pSymbol)
{
DWORD dwSymTag;
DWORD dwRVA;
DWORD dwSeg;
DWORD dwOff;
if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
return;
}
if (pSymbol->get_relativeVirtualAddress(&dwRVA) != S_OK) {
dwRVA = 0xFFFFFFFF;
}
pSymbol->get_addressSection(&dwSeg);
pSymbol->get_addressOffset(&dwOff);
wprintf(L"%s: [%08X][%04X:%08X] ", rgTags[dwSymTag], dwRVA, dwSeg, dwOff);
if (dwSymTag == SymTagThunk) {
BSTR bstrName;
if (pSymbol->get_name(&bstrName) == S_OK) {
wprintf(L"%s\n", bstrName);
SysFreeString(bstrName);
}
else {
if (pSymbol->get_targetRelativeVirtualAddress(&dwRVA) != S_OK) {
dwRVA = 0xFFFFFFFF;
}
pSymbol->get_targetSection(&dwSeg);
pSymbol->get_targetOffset(&dwOff);
wprintf(L"target -> [%08X][%04X:%08X]\n", dwRVA, dwSeg, dwOff);
}
}
else {
BSTR bstrName;
BSTR bstrUndname;
if (pSymbol->get_name(&bstrName) == S_OK) {
if (pSymbol->get_undecoratedName(&bstrUndname) == S_OK) {
wprintf(L"%s(%s)\n", bstrName, bstrUndname);
SysFreeString(bstrUndname);
}
else {
wprintf(L"%s\n", bstrName);
}
SysFreeString(bstrName);
}
}
}
////////////////////////////////////////////////////////////
// Print a callsite symbol info: SEG:OFF, RVA, type
//
void PrintCallSiteInfo(IDiaSymbol *pSymbol)
{
DWORD dwISect, dwOffset;
if (pSymbol->get_addressSection(&dwISect) == S_OK &&
pSymbol->get_addressOffset(&dwOffset) == S_OK) {
wprintf(L"[0x%04x:0x%08x] ", dwISect, dwOffset);
}
DWORD rva;
if (pSymbol->get_relativeVirtualAddress(&rva) == S_OK) {
wprintf(L"0x%08X ", rva);
}
IDiaSymbol *pFuncType;
if (pSymbol->get_type(&pFuncType) == S_OK) {
DWORD tag;
if (pFuncType->get_symTag(&tag) == S_OK) {
switch(tag)
{
case SymTagFunctionType:
PrintFunctionType(pSymbol);
break;
case SymTagPointerType:
PrintFunctionType(pFuncType);
break;
default:
wprintf(L"???\n");
break;
}
}
pFuncType->Release();
}
}
////////////////////////////////////////////////////////////
// Print a callsite symbol info: SEG:OFF, RVA, type
//
void PrintHeapAllocSite(IDiaSymbol *pSymbol)
{
DWORD dwISect, dwOffset;
if (pSymbol->get_addressSection(&dwISect) == S_OK &&
pSymbol->get_addressOffset(&dwOffset) == S_OK) {
wprintf(L"[0x%04x:0x%08x] ", dwISect, dwOffset);
}
DWORD rva;
if (pSymbol->get_relativeVirtualAddress(&rva) == S_OK) {
wprintf(L"0x%08X ", rva);
}
IDiaSymbol *pAllocType;
if (pSymbol->get_type(&pAllocType) == S_OK) {
PrintType(pAllocType);
pAllocType->Release();
}
}
////////////////////////////////////////////////////////////
// Print a COFF group symbol info: SEG:OFF, RVA, length, name
//
void PrintCoffGroup(IDiaSymbol *pSymbol)
{
DWORD dwISect, dwOffset;
if (pSymbol->get_addressSection(&dwISect) == S_OK &&
pSymbol->get_addressOffset(&dwOffset) == S_OK) {
wprintf(L"[0x%04x:0x%08x] ", dwISect, dwOffset);
}
DWORD rva;
if (pSymbol->get_relativeVirtualAddress(&rva) == S_OK) {
wprintf(L"0x%08X, ", rva);
}
ULONGLONG ulLen;
if (pSymbol->get_length(&ulLen) == S_OK) {
wprintf(L"len = %08X, ", (ULONG)ulLen);
}
DWORD characteristics;
if (pSymbol->get_characteristics(&characteristics) == S_OK) {
wprintf(L"characteristics = %08X, ", characteristics);
}
PrintName(pSymbol);
}
////////////////////////////////////////////////////////////
// Print a symbol info: name, type etc.
//
void PrintSymbol(IDiaSymbol *pSymbol, DWORD dwIndent)
{
IDiaSymbol *pType;
DWORD dwSymTag;
ULONGLONG ulLen;
if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
wprintf(L"ERROR - PrintSymbol get_symTag() failed\n");
return;
}
if (dwSymTag == SymTagFunction) {
putwchar(L'\n');
}
PrintSymTag(dwSymTag);
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
switch (dwSymTag) {
case SymTagCompilandDetails:
PrintCompilandDetails(pSymbol);
break;
case SymTagCompilandEnv:
PrintCompilandEnv(pSymbol);
break;
case SymTagData:
PrintData(pSymbol);
break;
case SymTagFunction:
case SymTagBlock:
PrintLocation(pSymbol);
if (pSymbol->get_length(&ulLen) == S_OK) {
wprintf(L", len = %08X, ", (ULONG)ulLen);
}
if (dwSymTag == SymTagFunction) {
DWORD dwCall;
if (pSymbol->get_callingConvention(&dwCall) == S_OK) {
wprintf(L", %s", SafeDRef(rgCallingConvention, dwCall));
}
}
PrintUndName(pSymbol);
putwchar(L'\n');
if (dwSymTag == SymTagFunction)
{
BOOL f;
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" Function attribute:");
if ((pSymbol->get_isCxxReturnUdt(&f) == S_OK) && f) {
wprintf(L" return user defined type (C++ style)");
}
if ((pSymbol->get_constructor(&f) == S_OK) && f) {
wprintf(L" instance constructor");
}
if ((pSymbol->get_isConstructorVirtualBase(&f) == S_OK) && f) {
wprintf(L" instance constructor of a class with virtual base");
}
putwchar (L'\n');
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" Function info:");
if ((pSymbol->get_hasAlloca(&f) == S_OK) && f) {
wprintf(L" alloca");
}
if ((pSymbol->get_hasSetJump(&f) == S_OK) && f) {
wprintf(L" setjmp");
}
if ((pSymbol->get_hasLongJump(&f) == S_OK) && f) {
wprintf(L" longjmp");
}
if ((pSymbol->get_hasInlAsm(&f) == S_OK) && f) {
wprintf(L" inlasm");
}
if ((pSymbol->get_hasEH(&f) == S_OK) && f) {
wprintf(L" eh");
}
if ((pSymbol->get_inlSpec(&f) == S_OK) && f) {
wprintf(L" inl_specified");
}
if ((pSymbol->get_hasSEH(&f) == S_OK) && f) {
wprintf(L" seh");
}
if ((pSymbol->get_isNaked(&f) == S_OK) && f) {
wprintf(L" naked");
}
if ((pSymbol->get_hasSecurityChecks(&f) == S_OK) && f) {
wprintf(L" gschecks");
}
if ((pSymbol->get_isSafeBuffers(&f) == S_OK) && f) {
wprintf(L" safebuffers");
}
if ((pSymbol->get_hasEHa(&f) == S_OK) && f) {
wprintf(L" asyncheh");
}
if ((pSymbol->get_noStackOrdering(&f) == S_OK) && f) {
wprintf(L" gsnostackordering");
}
if ((pSymbol->get_wasInlined(&f) == S_OK) && f) {
wprintf(L" wasinlined");
}
if ((pSymbol->get_strictGSCheck(&f) == S_OK) && f) {
wprintf(L" strict_gs_check");
}
putwchar(L'\n');
DWORD regnum;
if (pSymbol->get_paramBasePointerRegisterId(®num) == S_OK) {
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" parameter base pointer register: %s\n", SzNameC7Reg((USHORT) regnum));
}
if (pSymbol->get_localBasePointerRegisterId(®num) == S_OK) {
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" local base pointer register: %s\n", SzNameC7Reg((USHORT) regnum));
}
if ((pSymbol->get_framePointerPresent(&f) == S_OK) && f) {
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" Frame pointer present\n");
}
if ((pSymbol->get_optimizedCodeDebugInfo(&f) == S_OK) && f) {
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" Contains debug info for optimized code\n");
}
BSTR phaseName = NULL;
if (pSymbol->get_phaseName(&phaseName) == S_OK) {
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
wprintf(L" Phase Name: %s\n", static_cast<BSTR>(phaseName));
SysFreeString(phaseName);
}
}
IDiaEnumSymbols *pEnumChildren;
if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
IDiaSymbol *pChild;
ULONG celt = 0;
while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
PrintSymbol(pChild, dwIndent + 2);
pChild->Release();
}
pEnumChildren->Release();
}
return;
case SymTagAnnotation:
PrintLocation(pSymbol);
putwchar(L'\n');
break;
case SymTagLabel:
PrintLocation(pSymbol);
wprintf(L", ");
PrintName(pSymbol);
break;
case SymTagEnum:
case SymTagTypedef:
case SymTagUDT:
case SymTagBaseClass:
PrintUDT(pSymbol);
break;
case SymTagFuncDebugStart:
case SymTagFuncDebugEnd:
PrintLocation(pSymbol);
break;
case SymTagFunctionArgType:
case SymTagFunctionType:
case SymTagPointerType:
case SymTagArrayType:
case SymTagBaseType:
if (pSymbol->get_type(&pType) == S_OK) {
PrintType(pType);
pType->Release();
}
putwchar(L'\n');
break;
case SymTagThunk:
PrintThunk(pSymbol);
break;
case SymTagCallSite:
PrintCallSiteInfo(pSymbol);
break;
case SymTagHeapAllocationSite:
PrintHeapAllocSite(pSymbol);
break;
case SymTagCoffGroup:
PrintCoffGroup(pSymbol);
break;
default:
PrintName(pSymbol);
if (pSymbol->get_type(&pType) == S_OK) {
wprintf(L" has type ");
PrintType(pType);
pType->Release();
}
}
if ((dwSymTag == SymTagUDT) || (dwSymTag == SymTagAnnotation)) {
IDiaEnumSymbols *pEnumChildren;
putwchar(L'\n');
if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
IDiaSymbol *pChild;
ULONG celt = 0;
while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
PrintSymbol(pChild, dwIndent + 2);
pChild->Release();
}
pEnumChildren->Release();
}
}
putwchar(L'\n');
}
////////////////////////////////////////////////////////////
// Print the string coresponding to the symbol's tag property
//
void PrintSymTag(DWORD dwSymTag)
{
wprintf(L"%-15s: ", SafeDRef(rgTags, dwSymTag));
}
////////////////////////////////////////////////////////////
// Print the name of the symbol
//
void PrintName(IDiaSymbol *pSymbol)
{
BSTR bstrName;
BSTR bstrUndName;
if (pSymbol->get_name(&bstrName) != S_OK) {
wprintf(L"(none)");
return;
}
if (pSymbol->get_undecoratedName(&bstrUndName) == S_OK) {
if (wcscmp(bstrName, bstrUndName) == 0) {
wprintf(L"%s", bstrName);
}
else {
wprintf(L"%s(%s)", bstrUndName, bstrName);
}
SysFreeString(bstrUndName);
}
else {
wprintf(L"%s", bstrName);
}
SysFreeString(bstrName);
}
////////////////////////////////////////////////////////////
// Print the undecorated name of the symbol
// - only SymTagFunction, SymTagData and SymTagPublicSymbol
// can have this property set
//
void PrintUndName(IDiaSymbol *pSymbol)
{
BSTR bstrName;
if (pSymbol->get_undecoratedName(&bstrName) != S_OK) {
if (pSymbol->get_name(&bstrName) == S_OK) {
// Print the name of the symbol instead
wprintf(L"%s", (bstrName[0] != L'\0') ? bstrName : L"(none)");
SysFreeString(bstrName);
}
else {
wprintf(L"(none)");
}
return;
}
if (bstrName[0] != L'\0') {
wprintf(L"%s", bstrName);
}
SysFreeString(bstrName);
}
////////////////////////////////////////////////////////////
// Print a SymTagThunk symbol's info
//
void PrintThunk(IDiaSymbol *pSymbol)
{
DWORD dwRVA;
DWORD dwISect;
DWORD dwOffset;
if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
(pSymbol->get_addressSection(&dwISect) == S_OK) &&
(pSymbol->get_addressOffset(&dwOffset) == S_OK)) {
wprintf(L"[%08X][%04X:%08X]", dwRVA, dwISect, dwOffset);
}
if ((pSymbol->get_targetSection(&dwISect) == S_OK) &&
(pSymbol->get_targetOffset(&dwOffset) == S_OK) &&
(pSymbol->get_targetRelativeVirtualAddress(&dwRVA) == S_OK)) {
wprintf(L", target [%08X][%04X:%08X] ", dwRVA, dwISect, dwOffset);
}
else {
wprintf(L", target ");
PrintName(pSymbol);
}
}
////////////////////////////////////////////////////////////
// Print the compiland/module details: language, platform...
//
void PrintCompilandDetails(IDiaSymbol *pSymbol)
{
DWORD dwLanguage;
if (pSymbol->get_language(&dwLanguage) == S_OK) {
wprintf(L"\n\tLanguage: %s\n", SafeDRef(rgLanguage, dwLanguage));
}
DWORD dwPlatform;
if (pSymbol->get_platform(&dwPlatform) == S_OK) {
wprintf(L"\tTarget processor: %s\n", SafeDRef(rgProcessorStrings, dwPlatform));
}
BOOL fEC;
if (pSymbol->get_editAndContinueEnabled(&fEC) == S_OK) {
if (fEC) {
wprintf(L"\tCompiled for edit and continue: yes\n");
}
else {
wprintf(L"\tCompiled for edit and continue: no\n");
}
}
BOOL fDbgInfo;
if (pSymbol->get_hasDebugInfo(&fDbgInfo) == S_OK) {
if (fDbgInfo) {
wprintf(L"\tCompiled without debugging info: no\n");
}
else {
wprintf(L"\tCompiled without debugging info: yes\n");
}
}
BOOL fLTCG;
if (pSymbol->get_isLTCG(&fLTCG) == S_OK) {
if (fLTCG) {
wprintf(L"\tCompiled with LTCG: yes\n");
}
else {
wprintf(L"\tCompiled with LTCG: no\n");
}
}
BOOL fDataAlign;
if (pSymbol->get_isDataAligned(&fDataAlign) == S_OK) {
if (fDataAlign) {
wprintf(L"\tCompiled with /bzalign: no\n");
}
else {
wprintf(L"\tCompiled with /bzalign: yes\n");
}
}
BOOL fManagedPresent;
if (pSymbol->get_hasManagedCode(&fManagedPresent) == S_OK) {
if (fManagedPresent) {
wprintf(L"\tManaged code present: yes\n");
}
else {
wprintf(L"\tManaged code present: no\n");
}
}
BOOL fSecurityChecks;
if (pSymbol->get_hasSecurityChecks(&fSecurityChecks) == S_OK) {
if (fSecurityChecks) {
wprintf(L"\tCompiled with /GS: yes\n");
}
else {
wprintf(L"\tCompiled with /GS: no\n");
}
}
BOOL fSdl;
if (pSymbol->get_isSdl(&fSdl) == S_OK) {
if (fSdl) {
wprintf(L"\tCompiled with /sdl: yes\n");
}
else {
wprintf(L"\tCompiled with /sdl: no\n");
}
}
BOOL fHotPatch;
if (pSymbol->get_isHotpatchable(&fHotPatch) == S_OK) {
if (fHotPatch) {
wprintf(L"\tCompiled with /hotpatch: yes\n");
}
else {
wprintf(L"\tCompiled with /hotpatch: no\n");
}
}
BOOL fCVTCIL;
if (pSymbol->get_isCVTCIL(&fCVTCIL) == S_OK) {
if (fCVTCIL) {
wprintf(L"\tConverted by CVTCIL: yes\n");
}
else {
wprintf(L"\tConverted by CVTCIL: no\n");
}
}
BOOL fMSILModule;
if (pSymbol->get_isMSILNetmodule(&fMSILModule) == S_OK) {
if (fMSILModule) {
wprintf(L"\tMSIL module: yes\n");
}
else {
wprintf(L"\tMSIL module: no\n");
}
}
DWORD dwVerMajor;
DWORD dwVerMinor;
DWORD dwVerBuild;
DWORD dwVerQFE;
if ((pSymbol->get_frontEndMajor(&dwVerMajor) == S_OK) &&
(pSymbol->get_frontEndMinor(&dwVerMinor) == S_OK) &&
(pSymbol->get_frontEndBuild(&dwVerBuild) == S_OK)) {
wprintf(L"\tFrontend Version: Major = %u, Minor = %u, Build = %u",
dwVerMajor,
dwVerMinor,
dwVerBuild);
if (pSymbol->get_frontEndQFE(&dwVerQFE) == S_OK) {
wprintf(L", QFE = %u", dwVerQFE);
}
putwchar(L'\n');
}
if ((pSymbol->get_backEndMajor(&dwVerMajor) == S_OK) &&
(pSymbol->get_backEndMinor(&dwVerMinor) == S_OK) &&
(pSymbol->get_backEndBuild(&dwVerBuild) == S_OK)) {
wprintf(L"\tBackend Version: Major = %u, Minor = %u, Build = %u",
dwVerMajor,
dwVerMinor,
dwVerBuild);
if (pSymbol->get_backEndQFE(&dwVerQFE) == S_OK) {
wprintf(L", QFE = %u", dwVerQFE);
}
putwchar(L'\n');
}
BSTR bstrCompilerName;
if (pSymbol->get_compilerName(&bstrCompilerName) == S_OK) {
if (bstrCompilerName != NULL) {
wprintf(L"\tVersion string: %s", bstrCompilerName);
SysFreeString(bstrCompilerName);
}
}
putwchar(L'\n');
}
////////////////////////////////////////////////////////////
// Print the compilan/module env
//
void PrintCompilandEnv(IDiaSymbol *pSymbol)
{
PrintName(pSymbol);
wprintf(L" =");
VARIANT vt = { VT_EMPTY };
if (pSymbol->get_value(&vt) == S_OK) {
PrintVariant(vt);
VariantClear((VARIANTARG *) &vt);
}
}
////////////////////////////////////////////////////////////
// Print a string corespondig to a location type
//
void PrintLocation(IDiaSymbol *pSymbol)
{
DWORD dwLocType;
DWORD dwRVA, dwSect, dwOff, dwReg, dwBitPos, dwSlot;
LONG lOffset;
ULONGLONG ulLen;
VARIANT vt = { VT_EMPTY };
if (pSymbol->get_locationType(&dwLocType) != S_OK) {
// It must be a symbol in optimized code
wprintf(L"symbol in optmized code");
return;
}
switch (dwLocType) {
case LocIsStatic:
if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
(pSymbol->get_addressSection(&dwSect) == S_OK) &&
(pSymbol->get_addressOffset(&dwOff) == S_OK)) {
wprintf(L"%s, [%08X][%04X:%08X]", SafeDRef(rgLocationTypeString, dwLocType), dwRVA, dwSect, dwOff);
}
break;
case LocIsTLS:
case LocInMetaData:
case LocIsIlRel:
if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
(pSymbol->get_addressSection(&dwSect) == S_OK) &&
(pSymbol->get_addressOffset(&dwOff) == S_OK)) {
wprintf(L"%s, [%08X][%04X:%08X]", SafeDRef(rgLocationTypeString, dwLocType), dwRVA, dwSect, dwOff);
}
break;
case LocIsRegRel:
if ((pSymbol->get_registerId(&dwReg) == S_OK) &&
(pSymbol->get_offset(&lOffset) == S_OK)) {
wprintf(L"%s Relative, [%08X]", SzNameC7Reg((USHORT) dwReg), lOffset);
}
break;
case LocIsThisRel:
if (pSymbol->get_offset(&lOffset) == S_OK) {
wprintf(L"this+0x%X", lOffset);
}
break;
case LocIsBitField:
if ((pSymbol->get_offset(&lOffset) == S_OK) &&
(pSymbol->get_bitPosition(&dwBitPos) == S_OK) &&
(pSymbol->get_length(&ulLen) == S_OK)) {
wprintf(L"this(bf)+0x%X:0x%X len(0x%X)", lOffset, dwBitPos, (ULONG)ulLen);
}
break;
case LocIsEnregistered:
if (pSymbol->get_registerId(&dwReg) == S_OK) {
wprintf(L"enregistered %s", SzNameC7Reg((USHORT) dwReg));
}
break;
case LocIsSlot:
if (pSymbol->get_slot(&dwSlot) == S_OK) {
wprintf(L"%s, [%08X]", SafeDRef(rgLocationTypeString, dwLocType), dwSlot);
}
break;
case LocIsConstant:
wprintf(L"constant");
if (pSymbol->get_value(&vt) == S_OK) {
PrintVariant(vt);
VariantClear((VARIANTARG *) &vt);
}
break;
case LocIsNull:
break;
default :
wprintf(L"Error - invalid location type: 0x%X", dwLocType);
break;
}
}
////////////////////////////////////////////////////////////
// Print the type, value and the name of a const symbol
//
void PrintConst(IDiaSymbol *pSymbol)
{
PrintSymbolType(pSymbol);
VARIANT vt = { VT_EMPTY };
if (pSymbol->get_value(&vt) == S_OK) {
PrintVariant(vt);
VariantClear((VARIANTARG *) &vt);
}
PrintName(pSymbol);
}
////////////////////////////////////////////////////////////
// Print the name and the type of an user defined type
//
void PrintUDT(IDiaSymbol *pSymbol)
{
PrintName(pSymbol);
PrintSymbolType(pSymbol);
}
////////////////////////////////////////////////////////////
// Print a string representing the type of a symbol
//
void PrintSymbolType(IDiaSymbol *pSymbol)
{
IDiaSymbol *pType;
if (pSymbol->get_type(&pType) == S_OK) {
wprintf(L", Type: ");
PrintType(pType);
pType->Release();
}
}
////////////////////////////////////////////////////////////
// Print the information details for a type symbol
//
void PrintType(IDiaSymbol *pSymbol)
{
IDiaSymbol *pBaseType;
IDiaEnumSymbols *pEnumSym;
IDiaSymbol *pSym;
DWORD dwTag;
BSTR bstrName;
DWORD dwInfo;
BOOL bSet;
DWORD dwRank;
LONG lCount = 0;
ULONG celt = 1;
if (pSymbol->get_symTag(&dwTag) != S_OK) {
wprintf(L"ERROR - can't retrieve the symbol's SymTag\n");
return;
}
if (pSymbol->get_name(&bstrName) != S_OK) {
bstrName = NULL;
}
if (dwTag != SymTagPointerType) {
if ((pSymbol->get_constType(&bSet) == S_OK) && bSet) {
wprintf(L"const ");
}
if ((pSymbol->get_volatileType(&bSet) == S_OK) && bSet) {
wprintf(L"volatile ");
}
if ((pSymbol->get_unalignedType(&bSet) == S_OK) && bSet) {
wprintf(L"__unaligned ");
}
}
ULONGLONG ulLen;
pSymbol->get_length(&ulLen);
switch (dwTag) {
case SymTagUDT:
PrintUdtKind(pSymbol);
PrintName(pSymbol);
break;
case SymTagEnum:
wprintf(L"enum ");
PrintName(pSymbol);
break;
case SymTagFunctionType:
wprintf(L"function ");
break;
case SymTagPointerType:
if (pSymbol->get_type(&pBaseType) != S_OK) {
wprintf(L"ERROR - SymTagPointerType get_type");
if (bstrName != NULL) {
SysFreeString(bstrName);
}
return;
}
PrintType(pBaseType);
pBaseType->Release();
if ((pSymbol->get_reference(&bSet) == S_OK) && bSet) {
wprintf(L" &");
}
else {
wprintf(L" *");
}
if ((pSymbol->get_constType(&bSet) == S_OK) && bSet) {
wprintf(L" const");
}
if ((pSymbol->get_volatileType(&bSet) == S_OK) && bSet) {
wprintf(L" volatile");
}
if ((pSymbol->get_unalignedType(&bSet) == S_OK) && bSet) {
wprintf(L" __unaligned");
}
break;
case SymTagArrayType:
if (pSymbol->get_type(&pBaseType) == S_OK) {
PrintType(pBaseType);
if (pSymbol->get_rank(&dwRank) == S_OK) {
if (SUCCEEDED(pSymbol->findChildren(SymTagDimension, NULL, nsNone, &pEnumSym)) && (pEnumSym != NULL)) {
while (SUCCEEDED(pEnumSym->Next(1, &pSym, &celt)) && (celt == 1)) {
IDiaSymbol *pBound;
wprintf(L"[");
if (pSym->get_lowerBound(&pBound) == S_OK) {
PrintBound(pBound);
wprintf(L"..");
pBound->Release();
}
pBound = NULL;
if (pSym->get_upperBound(&pBound) == S_OK) {
PrintBound(pBound);
pBound->Release();
}
pSym->Release();
pSym = NULL;
wprintf(L"]");
}
pEnumSym->Release();
}
}
else if (SUCCEEDED(pSymbol->findChildren(SymTagCustomType, NULL, nsNone, &pEnumSym)) &&
(pEnumSym != NULL) &&
(pEnumSym->get_Count(&lCount) == S_OK) &&
(lCount > 0)) {
while (SUCCEEDED(pEnumSym->Next(1, &pSym, &celt)) && (celt == 1)) {
wprintf(L"[");
PrintType(pSym);
wprintf(L"]");
pSym->Release();
}
pEnumSym->Release();
}
else {
DWORD dwCountElems;
ULONGLONG ulLenArray;
ULONGLONG ulLenElem;
if (pSymbol->get_count(&dwCountElems) == S_OK) {
wprintf(L"[0x%X]", dwCountElems);
}
else if ((pSymbol->get_length(&ulLenArray) == S_OK) &&
(pBaseType->get_length(&ulLenElem) == S_OK)) {
if (ulLenElem == 0) {
wprintf(L"[0x%lX]", (ULONG)ulLenArray);
}
else {
wprintf(L"[0x%lX]", (ULONG)ulLenArray/ (ULONG)ulLenElem);
}
}
}
pBaseType->Release();
}
else {
wprintf(L"ERROR - SymTagArrayType get_type\n");
if (bstrName != NULL) {
SysFreeString(bstrName);
}
return;
}
break;
case SymTagBaseType:
if (pSymbol->get_baseType(&dwInfo) != S_OK) {
wprintf(L"SymTagBaseType get_baseType\n");
if (bstrName != NULL) {
SysFreeString(bstrName);
}
return;
}
switch (dwInfo) {
case btUInt :
wprintf(L"unsigned ");
// Fall through
case btInt :
switch (ulLen) {
case 1:
if (dwInfo == btInt) {
wprintf(L"signed ");
}
wprintf(L"char");
break;
case 2:
wprintf(L"short");
break;
case 4:
wprintf(L"int");
break;
case 8:
wprintf(L"__int64");
break;
}
dwInfo = 0xFFFFFFFF;
break;
case btFloat :
switch (ulLen) {
case 4:
wprintf(L"float");
break;
case 8:
wprintf(L"double");
break;
}
dwInfo = 0xFFFFFFFF;
break;
}
if (dwInfo == 0xFFFFFFFF) {
break;
}
wprintf(L"%s", rgBaseType[dwInfo]);
break;
case SymTagTypedef:
PrintName(pSymbol);
break;
case SymTagCustomType:
{
DWORD idOEM, idOEMSym;
DWORD cbData = 0;
DWORD count;
if (pSymbol->get_oemId(&idOEM) == S_OK) {
wprintf(L"OEMId = %X, ", idOEM);
}
if (pSymbol->get_oemSymbolId(&idOEMSym) == S_OK) {
wprintf(L"SymbolId = %X, ", idOEMSym);
}
if (pSymbol->get_types(0, &count, NULL) == S_OK) {
IDiaSymbol** rgpDiaSymbols = (IDiaSymbol**) _alloca(sizeof(IDiaSymbol *) * count);
if (pSymbol->get_types(count, &count, rgpDiaSymbols) == S_OK) {
for (ULONG i = 0; i < count; i++) {
PrintType(rgpDiaSymbols[i]);
rgpDiaSymbols[i]->Release();
}
}
}
// print custom data
if ((pSymbol->get_dataBytes(cbData, &cbData, NULL) == S_OK) && (cbData != 0)) {
wprintf(L", Data: ");
BYTE *pbData = new BYTE[cbData];
pSymbol->get_dataBytes(cbData, &cbData, pbData);
for (ULONG i = 0; i < cbData; i++) {
wprintf(L"0x%02X ", pbData[i]);
}
delete [] pbData;
}
}
break;
case SymTagData: // This really is member data, just print its location
PrintLocation(pSymbol);
break;
}
if (bstrName != NULL) {
SysFreeString(bstrName);
}
}
////////////////////////////////////////////////////////////
// Print bound information
//
void PrintBound(IDiaSymbol *pSymbol)
{
DWORD dwTag = 0;
DWORD dwKind;
if (pSymbol->get_symTag(&dwTag) != S_OK) {
wprintf(L"ERROR - PrintBound() get_symTag");
return;
}
if (pSymbol->get_locationType(&dwKind) != S_OK) {
wprintf(L"ERROR - PrintBound() get_locationType");
return;
}
if (dwTag == SymTagData && dwKind == LocIsConstant) {
VARIANT v = { VT_EMPTY };
if (pSymbol->get_value(&v) == S_OK) {
PrintVariant(v);
VariantClear((VARIANTARG *) &v);
}
}
else {
PrintName(pSymbol);
}
}
////////////////////////////////////////////////////////////
//
void PrintData(IDiaSymbol *pSymbol)
{
PrintLocation(pSymbol);
DWORD dwDataKind;
if (pSymbol->get_dataKind(&dwDataKind) != S_OK) {
wprintf(L"ERROR - PrintData() get_dataKind");
return;
}
wprintf(L", %s", SafeDRef(rgDataKind, dwDataKind));
PrintSymbolType(pSymbol);
wprintf(L", ");
PrintName(pSymbol);
}
////////////////////////////////////////////////////////////
// Print a VARIANT
//
void PrintVariant(VARIANT var)
{
switch (var.vt) {
case VT_UI1:
case VT_I1:
wprintf(L" 0x%X", var.bVal);
break;
case VT_I2:
case VT_UI2:
case VT_BOOL:
wprintf(L" 0x%X", var.iVal);
break;
case VT_I4:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_ERROR:
wprintf(L" 0x%X", var.lVal);
break;
case VT_R4:
wprintf(L" %g", var.fltVal);
break;
case VT_R8:
wprintf(L" %g", var.dblVal);
break;
case VT_BSTR:
wprintf(L" \"%s\"", var.bstrVal);
break;
default:
wprintf(L" ??");
}
}
////////////////////////////////////////////////////////////
// Print a string corresponding to a UDT kind
//
void PrintUdtKind(IDiaSymbol *pSymbol)
{
DWORD dwKind = 0;
if (pSymbol->get_udtKind(&dwKind) == S_OK) {
wprintf(L"%s ", rgUdtKind[dwKind]);
}
}
void PrintDiaTagValue(DiaTagValue *value) {
switch (value->valueSizeBytes) {
case 0:
wprintf(L"(none)");
break;
case 1:
wprintf(L"0x%X", *((UINT8 *)&value->value));
break;
case 2:
wprintf(L"0x%X", *((UINT16 *)&value->value));
break;
case 4:
wprintf(L"0x%I32X", *((UINT32 *)&value->value));
break;
case 8:
wprintf(L"0x%I64X", *((UINT64 *)&value->value));
break;
case 16: {
UINT64 lo = *((UINT64 *)(&value->value));
UINT64 hi = *((UINT64 *)(&value->value[8]));
if (hi == 0) {
wprintf(L"0x%llX\n", lo);
} else {
wprintf(L"0x%llX%016llX\n", hi, lo);
}
break;
}
default:
wprintf(L"??");
break;
}
}
void PrintIndent(DWORD dwIndent) {
for (DWORD i = 0; i < dwIndent; i++) {
putwchar(L' ');
}
}
////////////////////////////////////////////////////////////
// Print type informations is details
//
void PrintTypeInDetail(IDiaSymbol *pSymbol, DWORD dwIndent)
{
IDiaEnumSymbols *pEnumChildren;
IDiaSymbol *pType;
IDiaSymbol *pChild;
DWORD dwSymTag;
DWORD dwSymTagType;
ULONG celt = 0;
BOOL bFlag;
if (dwIndent > MAX_TYPE_IN_DETAIL) {
return;
}
if (pSymbol->get_symTag(&dwSymTag) != S_OK) {
wprintf(L"ERROR - PrintTypeInDetail() get_symTag\n");
return;
}
PrintSymTag(dwSymTag);
PrintIndent(dwIndent);
switch (dwSymTag) {
case SymTagData:
PrintData(pSymbol);
if (pSymbol->get_type(&pType) == S_OK) {
if (pType->get_symTag(&dwSymTagType) == S_OK) {
if (dwSymTagType == SymTagUDT) {
putwchar(L'\n');
PrintTypeInDetail(pType, dwIndent + 2);
}
}
pType->Release();
}
break;
case SymTagTypedef:
case SymTagVTable:
PrintSymbolType(pSymbol);
break;
case SymTagEnum:
case SymTagUDT:
PrintUDT(pSymbol);
putwchar(L'\n');
if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
PrintTypeInDetail(pChild, dwIndent + 2);
pChild->Release();
}
pEnumChildren->Release();
}
return;
break;
case SymTagFunction:
PrintFunctionType(pSymbol);
return;
break;
case SymTagPointerType:
PrintName(pSymbol);
wprintf(L" has type ");
PrintType(pSymbol);
break;
case SymTagArrayType:
case SymTagBaseType:
case SymTagFunctionArgType:
case SymTagUsingNamespace:
case SymTagCustom:
case SymTagFriend:
PrintName(pSymbol);
PrintSymbolType(pSymbol);
break;
case SymTagVTableShape:
case SymTagBaseClass:
PrintName(pSymbol);
if ((pSymbol->get_virtualBaseClass(&bFlag) == S_OK) && bFlag) {
IDiaSymbol *pVBTableType;
LONG ptrOffset;
DWORD dispIndex;
if ((pSymbol->get_virtualBaseDispIndex(&dispIndex) == S_OK) &&
(pSymbol->get_virtualBasePointerOffset(&ptrOffset) == S_OK)) {
wprintf(L" virtual, offset = 0x%X, pointer offset = %ld, virtual base pointer type = ", dispIndex, ptrOffset);
if (pSymbol->get_virtualBaseTableType(&pVBTableType) == S_OK) {
PrintType(pVBTableType);
pVBTableType->Release();
}
else {
wprintf(L"(unknown)");
}
}
}
else {
LONG offset;
if (pSymbol->get_offset(&offset) == S_OK) {
wprintf(L", offset = 0x%X", offset);
}
}
putwchar(L'\n');
if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
PrintTypeInDetail(pChild, dwIndent + 2);
pChild->Release();
}
pEnumChildren->Release();
}
break;
case SymTagFunctionType:
if (pSymbol->get_type(&pType) == S_OK) {
PrintType(pType);
}
break;
case SymTagThunk:
// Happens for functions which only have S_PROCREF
PrintThunk(pSymbol);
break;
case SymTagTaggedUnionCase: {
PrintName(pSymbol);
IDiaSymbol11* pSymbol11 = NULL;
IDiaSymbol* pTagType = NULL;
DWORD tagOffset = 0;
DiaTagValue mask;
if (SUCCEEDED(pSymbol->QueryInterface(&pSymbol11)) && pSymbol11->get_discriminatedUnionTag(&pTagType, &tagOffset, &mask) == S_OK) {
wprintf(L"\nTag : ");
PrintIndent(dwIndent);
wprintf(L"this+0x%X, Type: ", tagOffset);
PrintType(pTagType);
wprintf(L"\nTagMask : ");
PrintIndent(dwIndent);
PrintDiaTagValue(&mask);
}
putwchar(L'\n');
DWORD rangeSize = 0;
if (pSymbol11 && pSymbol11->get_tagRanges(0, &rangeSize, NULL) == S_OK) {
DiaTagValue *pTagValues = new DiaTagValue[rangeSize];
if (pSymbol11->get_tagRanges(rangeSize, &rangeSize, pTagValues) == S_OK) {
for (DWORD i = 0; i < rangeSize; i++) {
if (i % 2 == 0) {
wprintf(L"TagRange : ");
PrintIndent(dwIndent);
wprintf(L"low = ");
} else {
wprintf(L", high = ");
}
PrintDiaTagValue(&pTagValues[i]);
if (i % 2 == 1) {
putwchar(L'\n');
}
}
}
}
if (SUCCEEDED(pSymbol->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
PrintTypeInDetail(pChild, dwIndent + 2);
pChild->Release();
}
pEnumChildren->Release();
}
break;
}
default:
wprintf(L"ERROR - PrintTypeInDetail() invalid SymTag\n");
}
putwchar(L'\n');
}
////////////////////////////////////////////////////////////
// Print a function type
//
void PrintFunctionType(IDiaSymbol *pSymbol)
{
DWORD dwAccess = 0;
if (pSymbol->get_access(&dwAccess) == S_OK) {
wprintf(L"%s ", SafeDRef(rgAccess, dwAccess));
}
BOOL bIsStatic = FALSE;
if ((pSymbol->get_isStatic(&bIsStatic) == S_OK) && bIsStatic) {
wprintf(L"static ");
}
IDiaSymbol *pFuncType;
if (pSymbol->get_type(&pFuncType) == S_OK) {
IDiaSymbol *pReturnType;
if (pFuncType->get_type(&pReturnType) == S_OK) {
PrintType(pReturnType);
putwchar(L' ');
BSTR bstrName;
if (pSymbol->get_name(&bstrName) == S_OK) {
wprintf(L"%s", bstrName);
SysFreeString(bstrName);
}
IDiaEnumSymbols *pEnumChildren;
if (SUCCEEDED(pFuncType->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) {
IDiaSymbol *pChild;
ULONG celt = 0;
ULONG nParam = 0;
wprintf(L"(");
while (SUCCEEDED(pEnumChildren->Next(1, &pChild, &celt)) && (celt == 1)) {
IDiaSymbol *pType;
if (pChild->get_type(&pType) == S_OK) {
if (nParam++) {
wprintf(L", ");
}
PrintType(pType);
pType->Release();
}
pChild->Release();
}
pEnumChildren->Release();
wprintf(L")\n");
}
pReturnType->Release();
}
pFuncType->Release();
}
}
////////////////////////////////////////////////////////////
//
void PrintSourceFile(IDiaSourceFile *pSource)
{
BSTR bstrSourceName;
if (pSource->get_fileName(&bstrSourceName) == S_OK) {
wprintf(L"\t%s", bstrSourceName);
SysFreeString(bstrSourceName);
}
else {
wprintf(L"ERROR - PrintSourceFile() get_fileName");
return;
}
BYTE checksum[256];
DWORD cbChecksum = sizeof(checksum);
if (pSource->get_checksum(cbChecksum, &cbChecksum, checksum) == S_OK) {
wprintf(L" (");
DWORD checksumType;
if (pSource->get_checksumType(&checksumType) == S_OK) {
switch (checksumType) {
case CHKSUM_TYPE_NONE :
wprintf(L"None");
break;
case CHKSUM_TYPE_MD5 :
wprintf(L"MD5");
break;
case CHKSUM_TYPE_SHA1 :
wprintf(L"SHA1");
break;
default :
wprintf(L"0x%X", checksumType);
break;
}
if (cbChecksum != 0) {
wprintf(L": ");
}
}
for (DWORD ib = 0; ib < cbChecksum; ib++) {
wprintf(L"%02X", checksum[ib]);
}
wprintf(L")");
}
}
////////////////////////////////////////////////////////////
//
void PrintLines(IDiaSession *pSession, IDiaSymbol *pFunction)
{
DWORD dwSymTag;
if ((pFunction->get_symTag(&dwSymTag) != S_OK) || (dwSymTag != SymTagFunction)) {
wprintf(L"ERROR - PrintLines() dwSymTag != SymTagFunction");
return;
}
BSTR bstrName;
if (pFunction->get_name(&bstrName) == S_OK) {
wprintf(L"\n** %s\n\n", bstrName);
SysFreeString(bstrName);
}
ULONGLONG ulLength;
if (pFunction->get_length(&ulLength) != S_OK) {
wprintf(L"ERROR - PrintLines() get_length");
return;
}
DWORD dwRVA;
IDiaEnumLineNumbers *pLines;
if (pFunction->get_relativeVirtualAddress(&dwRVA) == S_OK) {
if (SUCCEEDED(pSession->findLinesByRVA(dwRVA, static_cast<DWORD>(ulLength), &pLines))) {
PrintLines(pLines);
pLines->Release();
}
}
else {
DWORD dwSect;
DWORD dwOffset;
if ((pFunction->get_addressSection(&dwSect) == S_OK) &&
(pFunction->get_addressOffset(&dwOffset) == S_OK)) {
if (SUCCEEDED(pSession->findLinesByAddr(dwSect, dwOffset, static_cast<DWORD>(ulLength), &pLines))) {
PrintLines(pLines);
pLines->Release();
}
}
}
}
////////////////////////////////////////////////////////////
//
void PrintLines(IDiaEnumLineNumbers *pLines)
{
IDiaLineNumber *pLine;
DWORD celt;
DWORD dwRVA;
DWORD dwSeg;
DWORD dwOffset;
DWORD dwLinenum;
DWORD dwSrcId;
DWORD dwLength;
DWORD dwSrcIdLast = (DWORD)(-1);
while (SUCCEEDED(pLines->Next(1, &pLine, &celt)) && (celt == 1)) {
if ((pLine->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
(pLine->get_addressSection(&dwSeg) == S_OK) &&
(pLine->get_addressOffset(&dwOffset) == S_OK) &&
(pLine->get_lineNumber(&dwLinenum) == S_OK) &&
(pLine->get_sourceFileId(&dwSrcId) == S_OK) &&
(pLine->get_length(&dwLength) == S_OK)) {
wprintf(L"\tline %u at [%08X][%04X:%08X], len = 0x%X", dwLinenum, dwRVA, dwSeg, dwOffset, dwLength);
if (dwSrcId != dwSrcIdLast) {
IDiaSourceFile *pSource;
if (pLine->get_sourceFile(&pSource) == S_OK) {
PrintSourceFile(pSource);
dwSrcIdLast = dwSrcId;
pSource->Release();
}
}
pLine->Release();
putwchar(L'\n');
}
}
}
////////////////////////////////////////////////////////////
// Print the section contribution data: name, Sec::Off, length
void PrintSecContribs(IDiaSectionContrib *pSegment)
{
DWORD dwRVA;
DWORD dwSect;
DWORD dwOffset;
DWORD dwLen;
IDiaSymbol *pCompiland;
BSTR bstrName;
if ((pSegment->get_relativeVirtualAddress(&dwRVA) == S_OK) &&
(pSegment->get_addressSection(&dwSect) == S_OK) &&
(pSegment->get_addressOffset(&dwOffset) == S_OK) &&
(pSegment->get_length(&dwLen) == S_OK) &&
(pSegment->get_compiland(&pCompiland) == S_OK) &&
(pCompiland->get_name(&bstrName) == S_OK)) {
wprintf(L" %08X %04X:%08X %08X %s\n", dwRVA, dwSect, dwOffset, dwLen, bstrName);
pCompiland->Release();
SysFreeString(bstrName);
}
}
////////////////////////////////////////////////////////////
// Print a debug stream data
//
void PrintStreamData(IDiaEnumDebugStreamData *pStream)
{
BSTR bstrName;
if (pStream->get_name(&bstrName) != S_OK) {
wprintf(L"ERROR - PrintStreamData() get_name\n");
}
else {
wprintf(L"Stream: %s", bstrName);
SysFreeString(bstrName);
}
LONG dwElem;
if (pStream->get_Count(&dwElem) != S_OK) {
wprintf(L"ERROR - PrintStreamData() get_Count\n");
}
else {
wprintf(L"(%u)\n", dwElem);
}
DWORD cbTotal = 0;
BYTE data[1024];
DWORD cbData;
ULONG celt = 0;
while (SUCCEEDED(pStream->Next(1, sizeof(data), &cbData, (BYTE *) &data, &celt)) && (celt == 1)) {
DWORD i;
for (i = 0; i < cbData; i++) {
wprintf(L"%02X ", data[i]);
if (i && (i % 8 == 7) && (i+1 < cbData)) {
wprintf(L"- ");
}
}
wprintf(L"| ");
for (i = 0; i < cbData; i++) {
wprintf(L"%c", iswprint(data[i]) ? data[i] : '.');
}
putwchar(L'\n');
cbTotal += cbData;
}
wprintf(L"Summary :\n\tNo of Elems = %u\n", dwElem);
if (dwElem != 0) {
wprintf(L"\tSizeof(Elem) = %u\n", cbTotal / dwElem);
}
putwchar(L'\n');
}
////////////////////////////////////////////////////////////
// Print the FPO info for a given symbol;
//
void PrintFrameData(IDiaFrameData *pFrameData)
{
DWORD dwSect;
DWORD dwOffset;
DWORD cbBlock;
DWORD cbLocals; // Number of bytes reserved for the function locals
DWORD cbParams; // Number of bytes reserved for the function arguments
DWORD cbMaxStack;
DWORD cbProlog;
DWORD cbSavedRegs;
BOOL bSEH;
BOOL bEH;
BOOL bStart;
if ((pFrameData->get_addressSection(&dwSect) == S_OK) &&
(pFrameData->get_addressOffset(&dwOffset) == S_OK) &&
(pFrameData->get_lengthBlock(&cbBlock) == S_OK) &&
(pFrameData->get_lengthLocals(&cbLocals) == S_OK) &&
(pFrameData->get_lengthParams(&cbParams) == S_OK) &&
(pFrameData->get_maxStack(&cbMaxStack) == S_OK) &&
(pFrameData->get_lengthProlog(&cbProlog) == S_OK) &&
(pFrameData->get_lengthSavedRegisters(&cbSavedRegs) == S_OK) &&
(pFrameData->get_systemExceptionHandling(&bSEH) == S_OK) &&
(pFrameData->get_cplusplusExceptionHandling(&bEH) == S_OK) &&
(pFrameData->get_functionStart(&bStart) == S_OK)) {
wprintf(L"%04X:%08X %8X %8X %8X %8X %8X %8X %c %c %c",
dwSect, dwOffset, cbBlock, cbLocals, cbParams, cbMaxStack, cbProlog, cbSavedRegs,
bSEH ? L'Y' : L'N',
bEH ? L'Y' : L'N',
bStart ? L'Y' : L'N');
BSTR bstrProgram;
if (pFrameData->get_program(&bstrProgram) == S_OK) {
wprintf(L" %s", bstrProgram);
SysFreeString(bstrProgram);
}
putwchar(L'\n');
}
}
////////////////////////////////////////////////////////////
// Print all the valid properties associated to a symbol
//
void PrintPropertyStorage(IDiaPropertyStorage *pPropertyStorage)
{
IEnumSTATPROPSTG *pEnumProps;
if (SUCCEEDED(pPropertyStorage->Enum(&pEnumProps))) {
STATPROPSTG prop;
DWORD celt = 1;
while (SUCCEEDED(pEnumProps->Next(celt, &prop, &celt)) && (celt == 1)) {
PROPSPEC pspec = { PRSPEC_PROPID, prop.propid };
PROPVARIANT vt = { VT_EMPTY };
if (SUCCEEDED(pPropertyStorage->ReadMultiple(1, &pspec, &vt))) {
switch (vt.vt) {
case VT_BOOL:
wprintf(L"%32s:\t %s\n", prop.lpwstrName, vt.bVal ? L"true" : L"false");
break;
case VT_I2:
wprintf(L"%32s:\t %d\n", prop.lpwstrName, vt.iVal);
break;
case VT_UI2:
wprintf(L"%32s:\t %u\n", prop.lpwstrName, vt.uiVal);
break;
case VT_I4:
wprintf(L"%32s:\t %d\n", prop.lpwstrName, vt.intVal);
break;
case VT_UI4:
wprintf(L"%32s:\t 0x%0X\n", prop.lpwstrName, vt.uintVal);
break;
case VT_UI8:
wprintf(L"%32s:\t 0x%llX\n", prop.lpwstrName, vt.uhVal.QuadPart);
break;
case VT_BSTR:
wprintf(L"%32s:\t %s\n", prop.lpwstrName, vt.bstrVal);
break;
case VT_UNKNOWN:
wprintf(L"%32s:\t %p\n", prop.lpwstrName, vt.punkVal);
break;
case VT_SAFEARRAY:
break;
}
VariantClear((VARIANTARG *) &vt);
}
SysFreeString( prop.lpwstrName );
}
pEnumProps->Release();
}
}