summaryrefslogtreecommitdiff
path: root/src/ToolBox/PdbTypeMatch/PrintSymbol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ToolBox/PdbTypeMatch/PrintSymbol.cpp')
-rw-r--r--src/ToolBox/PdbTypeMatch/PrintSymbol.cpp2254
1 files changed, 2254 insertions, 0 deletions
diff --git a/src/ToolBox/PdbTypeMatch/PrintSymbol.cpp b/src/ToolBox/PdbTypeMatch/PrintSymbol.cpp
new file mode 100644
index 0000000000..41e3d4cf0e
--- /dev/null
+++ b/src/ToolBox/PdbTypeMatch/PrintSymbol.cpp
@@ -0,0 +1,2254 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// PrintSymbol.cpp : Defines the printing procedures for the symbols
+//
+// This is a part of the Debug Interface Access SDK
+//
+// 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"
+#include <comdef.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
+};
+
+// 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
+};
+
+
+// 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", // CV_CFL_THUMB
+};
+
+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"enum",
+};
+
+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_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
+};
+
+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"
+};
+
+
+////////////////////////////////////////////////////////////
+// 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 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, dwIndent + 2);
+ break;
+
+ case SymTagFunction:
+ case SymTagBlock:
+ PrintLocation(pSymbol);
+
+ if (pSymbol->get_length(&ulLen) == S_OK) {
+ wprintf(L", len = %08X, ", 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');
+ }
+
+ 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;
+
+ default:
+ PrintName(pSymbol);
+
+ IDiaSymbol *pType;
+
+ 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);
+}
+
+void GetSymbolName(std::wstring& symbolName, IDiaSymbol *pSymbol)
+{
+ BSTR bstrName;
+ BSTR bstrUndName;
+
+ if (pSymbol->get_name(&bstrName) != S_OK) {
+ symbolName.clear();
+ return;
+ }
+
+ if (pSymbol->get_undecoratedName(&bstrUndName) == S_OK) {
+ if (wcscmp(bstrName, bstrUndName) == 0)
+ {
+ symbolName= _bstr_t(bstrName);
+ }
+ else
+ {
+ symbolName= _bstr_t(bstrUndName);
+ }
+
+ SysFreeString(bstrUndName);
+ }
+
+ else
+ {
+ symbolName= _bstr_t(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 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, 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]", ulLenArray);
+ }
+
+ else {
+ wprintf(L"[0x%lX]", ulLenArray/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;
+
+ if (pSymbol->get_value(&v) == S_OK) {
+ PrintVariant(v);
+ VariantClear((VARIANTARG *) &v);
+ }
+ }
+
+ else {
+ PrintName(pSymbol);
+ }
+}
+
+////////////////////////////////////////////////////////////
+//
+void PrintData(IDiaSymbol *pSymbol, DWORD dwIndent)
+{
+ 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]);
+ }
+}
+
+////////////////////////////////////////////////////////////
+// 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);
+
+ for (DWORD i = 0;i < dwIndent; i++) {
+ putwchar(L' ');
+ }
+
+ switch (dwSymTag) {
+ case SymTagData:
+ PrintData(pSymbol, dwIndent);
+
+ 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;
+
+ 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%X\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();
+ }
+}