├── .gitignore ├── Callback.h ├── DIA2Dump.vcxproj ├── DIA2Dump.vcxproj.filters ├── DIA_SDK ├── bin │ ├── amd64 │ │ └── msdia140.dll │ ├── arm │ │ └── msdia140.dll │ └── msdia140.dll ├── idl │ ├── Dia2Lib.dll │ ├── dia2.h │ ├── dia2.idl │ ├── dia2.tlb │ ├── dia2_i.c │ ├── dia2_p.c │ ├── dlldata.c │ └── gen.cmd ├── include │ ├── cvconst.h │ ├── dia2.h │ └── diacreate.h └── lib │ ├── amd64 │ └── diaguids.lib │ ├── arm │ └── diaguids.lib │ └── diaguids.lib ├── PrintSymbol.cpp ├── PrintSymbol.h ├── README.md ├── dia2dump.cpp ├── dia2dump.h ├── regs.cpp ├── regs.h ├── stdafx.cpp ├── stdafx.h ├── x_common.h ├── x_cpp_enum.h ├── x_cpp_gen_file.h ├── x_cpp_proxy.h ├── x_meta.h ├── x_names.h ├── x_print.h ├── x_ripper.cpp ├── x_str.h └── x_udt.h /.gitignore: -------------------------------------------------------------------------------- 1 | _bin/ 2 | _obj/ 3 | 4 | .vs/ 5 | 6 | *.sln 7 | *.suo 8 | *.sdf 9 | *.opensdf 10 | *.db 11 | *.opendb 12 | *.exe 13 | *.pdb 14 | -------------------------------------------------------------------------------- /Callback.h: -------------------------------------------------------------------------------- 1 | #include "dia2.h" 2 | 3 | #pragma warning ( disable : 4100) 4 | 5 | class CCallback : public IDiaLoadCallback2{ 6 | int m_nRefCount; 7 | public: 8 | CCallback() { m_nRefCount = 0; } 9 | 10 | //IUnknown 11 | ULONG STDMETHODCALLTYPE AddRef() { 12 | m_nRefCount++; 13 | return m_nRefCount; 14 | } 15 | ULONG STDMETHODCALLTYPE Release() { 16 | if ( (--m_nRefCount) == 0 ) 17 | delete this; 18 | return m_nRefCount; 19 | } 20 | HRESULT STDMETHODCALLTYPE QueryInterface( REFIID rid, void **ppUnk ) { 21 | if ( ppUnk == NULL ) { 22 | return E_INVALIDARG; 23 | } 24 | if (rid == __uuidof( IDiaLoadCallback2 ) ) 25 | *ppUnk = (IDiaLoadCallback2 *)this; 26 | else if (rid == __uuidof( IDiaLoadCallback ) ) 27 | *ppUnk = (IDiaLoadCallback *)this; 28 | else if (rid == __uuidof( IUnknown ) ) 29 | *ppUnk = (IUnknown *)this; 30 | else 31 | *ppUnk = NULL; 32 | if ( *ppUnk != NULL ) { 33 | AddRef(); 34 | return S_OK; 35 | } 36 | return E_NOINTERFACE; 37 | } 38 | 39 | HRESULT STDMETHODCALLTYPE NotifyDebugDir( 40 | BOOL fExecutable, 41 | DWORD cbData, 42 | BYTE data[]) // really a const struct _IMAGE_DEBUG_DIRECTORY * 43 | { 44 | return S_OK; 45 | } 46 | HRESULT STDMETHODCALLTYPE NotifyOpenDBG( 47 | LPCOLESTR dbgPath, 48 | HRESULT resultCode) 49 | { 50 | // wprintf(L"opening %s...\n", dbgPath); 51 | return S_OK; 52 | } 53 | 54 | HRESULT STDMETHODCALLTYPE NotifyOpenPDB( 55 | LPCOLESTR pdbPath, 56 | HRESULT resultCode) 57 | { 58 | // wprintf(L"opening %s...\n", pdbPath); 59 | return S_OK; 60 | } 61 | HRESULT STDMETHODCALLTYPE RestrictRegistryAccess() 62 | { 63 | // return hr != S_OK to prevent querying the registry for symbol search paths 64 | return S_OK; 65 | } 66 | HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess() 67 | { 68 | // return hr != S_OK to prevent accessing a symbol server 69 | return S_OK; 70 | } 71 | HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess() 72 | { 73 | // return hr != S_OK to prevent querying the registry for symbol search paths 74 | return S_OK; 75 | } 76 | HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess() 77 | { 78 | // return hr != S_OK to prevent accessing a symbol server 79 | return S_OK; 80 | } 81 | HRESULT STDMETHODCALLTYPE RestrictDBGAccess() 82 | { 83 | return S_OK; 84 | } 85 | HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess() 86 | { 87 | return S_OK; 88 | } 89 | }; 90 | 91 | #pragma warning ( default : 4100 ) 92 | -------------------------------------------------------------------------------- /DIA2Dump.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {785BAA40-99C8-491E-B95B-A7EA0A8ABC78} 15 | Dia2Dump 16 | 10.0 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | $(VSInstallDir)\DIA SDK\include;$(IncludePath) 44 | $(VSInstallDir)\DIA SDK\lib;$(LibraryPath) 45 | $(SolutionDir)_bin\$(Platform)\$(Configuration)\ 46 | $(SolutionDir)_obj\$(Platform)\$(Configuration)\ 47 | 48 | 49 | $(VSInstallDir)\DIA SDK\include;$(IncludePath) 50 | $(VSInstallDir)\DIA SDK\lib;$(LibraryPath) 51 | $(SolutionDir)_bin\$(Platform)\$(Configuration)\ 52 | $(SolutionDir)_obj\$(Platform)\$(Configuration)\ 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | Use 59 | ProgramDatabase 60 | DIA_SDK\include\;%(AdditionalIncludeDirectories) 61 | false 62 | true 63 | 64 | 65 | true 66 | 10485760 67 | DIA_SDK\lib\amd64\;%(AdditionalLibraryDirectories) 68 | 69 | 70 | 71 | 72 | Level3 73 | MaxSpeed 74 | true 75 | false 76 | Use 77 | DIA_SDK\include\;%(AdditionalIncludeDirectories) 78 | ProgramDatabase 79 | AnySuitable 80 | MultiThreaded 81 | false 82 | true 83 | 84 | 85 | true 86 | true 87 | true 88 | DIA_SDK\lib\amd64\;%(AdditionalLibraryDirectories) 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | Create 114 | Create 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /DIA2Dump.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {a117e75c-50ec-46bd-ae1e-4097d2f0f7ae} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | _custom 38 | 39 | 40 | _custom 41 | 42 | 43 | _custom 44 | 45 | 46 | _custom 47 | 48 | 49 | _custom 50 | 51 | 52 | _custom 53 | 54 | 55 | _custom 56 | 57 | 58 | _custom 59 | 60 | 61 | _custom 62 | 63 | 64 | 65 | 66 | Source Files 67 | 68 | 69 | Source Files 70 | 71 | 72 | Source Files 73 | 74 | 75 | Source Files 76 | 77 | 78 | _custom 79 | 80 | 81 | -------------------------------------------------------------------------------- /DIA_SDK/bin/amd64/msdia140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/bin/amd64/msdia140.dll -------------------------------------------------------------------------------- /DIA_SDK/bin/arm/msdia140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/bin/arm/msdia140.dll -------------------------------------------------------------------------------- /DIA_SDK/bin/msdia140.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/bin/msdia140.dll -------------------------------------------------------------------------------- /DIA_SDK/idl/Dia2Lib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/idl/Dia2Lib.dll -------------------------------------------------------------------------------- /DIA_SDK/idl/dia2.tlb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/idl/dia2.tlb -------------------------------------------------------------------------------- /DIA_SDK/idl/dia2_i.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ 4 | 5 | /* link this file in with the server and any clients */ 6 | 7 | 8 | /* File created by MIDL compiler version 8.01.0622 */ 9 | /* at Tue Jan 19 05:14:07 2038 10 | */ 11 | /* Compiler settings for C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\\DIA SDK\idl\dia2.idl: 12 | Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 13 | protocol : dce , ms_ext, c_ext, robust 14 | error checks: allocation ref bounds_check enum stub_data 15 | VC __declspec() decoration level: 16 | __declspec(uuid()), __declspec(selectany), __declspec(novtable) 17 | DECLSPEC_UUID(), MIDL_INTERFACE() 18 | */ 19 | /* @@MIDL_FILE_HEADING( ) */ 20 | 21 | #pragma warning( disable: 4049 ) /* more than 64k source lines */ 22 | 23 | 24 | #ifdef __cplusplus 25 | extern "C"{ 26 | #endif 27 | 28 | 29 | #include 30 | #include 31 | 32 | #ifdef _MIDL_USE_GUIDDEF_ 33 | 34 | #ifndef INITGUID 35 | #define INITGUID 36 | #include 37 | #undef INITGUID 38 | #else 39 | #include 40 | #endif 41 | 42 | #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ 43 | DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) 44 | 45 | #else // !_MIDL_USE_GUIDDEF_ 46 | 47 | #ifndef __IID_DEFINED__ 48 | #define __IID_DEFINED__ 49 | 50 | typedef struct _IID 51 | { 52 | unsigned long x; 53 | unsigned short s1; 54 | unsigned short s2; 55 | unsigned char c[8]; 56 | } IID; 57 | 58 | #endif // __IID_DEFINED__ 59 | 60 | #ifndef CLSID_DEFINED 61 | #define CLSID_DEFINED 62 | typedef IID CLSID; 63 | #endif // CLSID_DEFINED 64 | 65 | #define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ 66 | EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}} 67 | 68 | #endif // !_MIDL_USE_GUIDDEF_ 69 | 70 | MIDL_DEFINE_GUID(IID, IID_IDiaLoadCallback,0xC32ADB82,0x73F4,0x421b,0x95,0xD5,0xA4,0x70,0x6E,0xDF,0x5D,0xBE); 71 | 72 | 73 | MIDL_DEFINE_GUID(IID, IID_IDiaLoadCallback2,0x4688a074,0x5a4d,0x4486,0xae,0xa8,0x7b,0x90,0x71,0x1d,0x9f,0x7c); 74 | 75 | 76 | MIDL_DEFINE_GUID(IID, IID_IDiaReadExeAtOffsetCallback,0x587A461C,0xB80B,0x4f54,0x91,0x94,0x50,0x32,0x58,0x9A,0x63,0x19); 77 | 78 | 79 | MIDL_DEFINE_GUID(IID, IID_IDiaReadExeAtRVACallback,0x8E3F80CA,0x7517,0x432a,0xBA,0x07,0x28,0x51,0x34,0xAA,0xEA,0x8E); 80 | 81 | 82 | MIDL_DEFINE_GUID(IID, IID_IDiaDataSource,0x79F1BB5F,0xB66E,0x48e5,0xB6,0xA9,0x15,0x45,0xC3,0x23,0xCA,0x3D); 83 | 84 | 85 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumSymbols,0xCAB72C48,0x443B,0x48f5,0x9B,0x0B,0x42,0xF0,0x82,0x0A,0xB2,0x9A); 86 | 87 | 88 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumSymbolsByAddr,0x624B7D9C,0x24EA,0x4421,0x9D,0x06,0x3B,0x57,0x74,0x71,0xC1,0xFA); 89 | 90 | 91 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumSourceFiles,0x10F3DBD9,0x664F,0x4469,0xB8,0x08,0x94,0x71,0xC7,0xA5,0x05,0x38); 92 | 93 | 94 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumInputAssemblyFiles,0x1C7FF653,0x51F7,0x457E,0x84,0x19,0xB2,0x0F,0x57,0xEF,0x7E,0x4D); 95 | 96 | 97 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumLineNumbers,0xFE30E878,0x54AC,0x44f1,0x81,0xBA,0x39,0xDE,0x94,0x0F,0x60,0x52); 98 | 99 | 100 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumInjectedSources,0xD5612573,0x6925,0x4468,0x88,0x83,0x98,0xCD,0xEC,0x8C,0x38,0x4A); 101 | 102 | 103 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumSegments,0xE8368CA9,0x01D1,0x419d,0xAC,0x0C,0xE3,0x12,0x35,0xDB,0xDA,0x9F); 104 | 105 | 106 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumSectionContribs,0x1994DEB2,0x2C82,0x4b1d,0xA5,0x7F,0xAF,0xF4,0x24,0xD5,0x4A,0x68); 107 | 108 | 109 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumFrameData,0x9FC77A4B,0x3C1C,0x44ed,0xA7,0x98,0x6C,0x1D,0xEE,0xA5,0x3E,0x1F); 110 | 111 | 112 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumDebugStreamData,0x486943E8,0xD187,0x4a6b,0xA3,0xC4,0x29,0x12,0x59,0xFF,0xF6,0x0D); 113 | 114 | 115 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumDebugStreams,0x08CBB41E,0x47A6,0x4f87,0x92,0xF1,0x1C,0x9C,0x87,0xCE,0xD0,0x44); 116 | 117 | 118 | MIDL_DEFINE_GUID(IID, IID_IDiaAddressMap,0xB62A2E7A,0x067A,0x4ea3,0xB5,0x98,0x04,0xC0,0x97,0x17,0x50,0x2C); 119 | 120 | 121 | MIDL_DEFINE_GUID(IID, IID_IDiaSession,0x2F609EE1,0xD1C8,0x4E24,0x82,0x88,0x33,0x26,0xBA,0xDC,0xD2,0x11); 122 | 123 | 124 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol,0xcb787b2f,0xbd6c,0x4635,0xba,0x52,0x93,0x31,0x26,0xbd,0x2d,0xcd); 125 | 126 | 127 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol2,0x611e86cd,0xb7d1,0x4546,0x8a,0x15,0x07,0x0e,0x2b,0x07,0xa4,0x27); 128 | 129 | 130 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol3,0x99b665f7,0xc1b2,0x49d3,0x89,0xb2,0xa3,0x84,0x36,0x1a,0xca,0xb5); 131 | 132 | 133 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol4,0xbf6c88a7,0xe9d6,0x4346,0x99,0xa1,0xd0,0x53,0xde,0x5a,0x78,0x08); 134 | 135 | 136 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol5,0xabe2de00,0xdc2d,0x4793,0xaf,0x9a,0xef,0x1d,0x90,0x83,0x26,0x44); 137 | 138 | 139 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol6,0x8133dad3,0x75fe,0x4234,0xac,0x7e,0xf8,0xe7,0xa1,0xd3,0xcb,0xb3); 140 | 141 | 142 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol7,0x64ce6cd5,0x7315,0x4328,0x86,0xd6,0x10,0xe3,0x03,0xe0,0x10,0xb4); 143 | 144 | 145 | MIDL_DEFINE_GUID(IID, IID_IDiaSymbol8,0x7f2e041f,0x1294,0x41bd,0xb8,0x3a,0xe7,0x15,0x97,0x2d,0x2c,0xe3); 146 | 147 | 148 | MIDL_DEFINE_GUID(IID, IID_IDiaSourceFile,0xA2EF5353,0xF5A8,0x4eb3,0x90,0xD2,0xCB,0x52,0x6A,0xCB,0x3C,0xDD); 149 | 150 | 151 | MIDL_DEFINE_GUID(IID, IID_IDiaInputAssemblyFile,0x3BFE56B0,0x390C,0x4863,0x94,0x30,0x1F,0x3D,0x08,0x3B,0x76,0x84); 152 | 153 | 154 | MIDL_DEFINE_GUID(IID, IID_IDiaLineNumber,0xB388EB14,0xBE4D,0x421d,0xA8,0xA1,0x6C,0xF7,0xAB,0x05,0x70,0x86); 155 | 156 | 157 | MIDL_DEFINE_GUID(IID, IID_IDiaSectionContrib,0x0CF4B60E,0x35B1,0x4c6c,0xBD,0xD8,0x85,0x4B,0x9C,0x8E,0x38,0x57); 158 | 159 | 160 | MIDL_DEFINE_GUID(IID, IID_IDiaSegment,0x0775B784,0xC75B,0x4449,0x84,0x8B,0xB7,0xBD,0x31,0x59,0x54,0x5B); 161 | 162 | 163 | MIDL_DEFINE_GUID(IID, IID_IDiaInjectedSource,0xAE605CDC,0x8105,0x4a23,0xB7,0x10,0x32,0x59,0xF1,0xE2,0x61,0x12); 164 | 165 | 166 | MIDL_DEFINE_GUID(IID, IID_IDiaStackWalkFrame,0x07C590C1,0x438D,0x4F47,0xBD,0xCD,0x43,0x97,0xBC,0x81,0xAD,0x75); 167 | 168 | 169 | MIDL_DEFINE_GUID(IID, IID_IDiaFrameData,0xA39184B7,0x6A36,0x42de,0x8E,0xEC,0x7D,0xF9,0xF3,0xF5,0x9F,0x33); 170 | 171 | 172 | MIDL_DEFINE_GUID(IID, IID_IDiaImageData,0xC8E40ED2,0xA1D9,0x4221,0x86,0x92,0x3C,0xE6,0x61,0x18,0x4B,0x44); 173 | 174 | 175 | MIDL_DEFINE_GUID(IID, IID_IDiaTable,0x4A59FB77,0xABAC,0x469b,0xA3,0x0B,0x9E,0xCC,0x85,0xBF,0xEF,0x14); 176 | 177 | 178 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumTables,0xC65C2B0A,0x1150,0x4d7a,0xAF,0xCC,0xE0,0x5B,0xF3,0xDE,0xE8,0x1E); 179 | 180 | 181 | MIDL_DEFINE_GUID(IID, LIBID_Dia2Lib,0x106173A0,0x0173,0x4e5c,0x84,0xE7,0xE9,0x15,0x42,0x2B,0xE9,0x97); 182 | 183 | 184 | MIDL_DEFINE_GUID(CLSID, CLSID_DiaSource,0xe6756135,0x1e65,0x4d17,0x85,0x76,0x61,0x07,0x61,0x39,0x8c,0x3c); 185 | 186 | 187 | MIDL_DEFINE_GUID(CLSID, CLSID_DiaSourceAlt,0x91904831,0x49ca,0x4766,0xb9,0x5c,0x25,0x39,0x7e,0x2d,0xd6,0xdc); 188 | 189 | 190 | MIDL_DEFINE_GUID(CLSID, CLSID_DiaStackWalker,0xce4a85db,0x5768,0x475b,0xa4,0xe1,0xc0,0xbc,0xa2,0x11,0x2a,0x6b); 191 | 192 | 193 | MIDL_DEFINE_GUID(IID, IID_IDiaPropertyStorage,0x9d416f9c,0xe184,0x45b2,0xa4,0xf0,0xce,0x51,0x7f,0x71,0x9e,0x9b); 194 | 195 | 196 | MIDL_DEFINE_GUID(IID, IID_IDiaStackFrame,0x5edbc96d,0xcdd6,0x4792,0xaf,0xbe,0xcc,0x89,0x00,0x7d,0x96,0x10); 197 | 198 | 199 | MIDL_DEFINE_GUID(IID, IID_IDiaEnumStackFrames,0xec9d461d,0xce74,0x4711,0xa0,0x20,0x7d,0x8f,0x9a,0x1d,0xd2,0x55); 200 | 201 | 202 | MIDL_DEFINE_GUID(IID, IID_IDiaStackWalkHelper,0x21F81B1B,0xC5BB,0x42A3,0xBC,0x4F,0xCC,0xBA,0xA7,0x5B,0x9F,0x19); 203 | 204 | 205 | MIDL_DEFINE_GUID(IID, IID_IDiaStackWalker,0x5485216b,0xa54c,0x469f,0x96,0x70,0x52,0xb2,0x4d,0x52,0x29,0xbb); 206 | 207 | 208 | MIDL_DEFINE_GUID(IID, IID_IDiaStackWalkHelper2,0x8222c490,0x507b,0x4bef,0xb3,0xbd,0x41,0xdc,0xa7,0xb5,0x93,0x4c); 209 | 210 | 211 | MIDL_DEFINE_GUID(IID, IID_IDiaStackWalker2,0x7c185885,0xa015,0x4cac,0x94,0x11,0x0f,0x4f,0xb3,0x9b,0x1f,0x3a); 212 | 213 | #undef MIDL_DEFINE_GUID 214 | 215 | #ifdef __cplusplus 216 | } 217 | #endif 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /DIA_SDK/idl/dia2_p.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* this ALWAYS GENERATED file contains the proxy stub code */ 4 | 5 | 6 | /* File created by MIDL compiler version 8.01.0622 */ 7 | /* at Tue Jan 19 05:14:07 2038 8 | */ 9 | /* Compiler settings for C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\\DIA SDK\idl\dia2.idl: 10 | Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 11 | protocol : dce , ms_ext, c_ext, robust 12 | error checks: allocation ref bounds_check enum stub_data 13 | VC __declspec() decoration level: 14 | __declspec(uuid()), __declspec(selectany), __declspec(novtable) 15 | DECLSPEC_UUID(), MIDL_INTERFACE() 16 | */ 17 | /* @@MIDL_FILE_HEADING( ) */ 18 | 19 | #if !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_) 20 | 21 | 22 | #pragma warning( disable: 4049 ) /* more than 64k source lines */ 23 | #if _MSC_VER >= 1200 24 | #pragma warning(push) 25 | #endif 26 | 27 | #pragma warning( disable: 4211 ) /* redefine extern to static */ 28 | #pragma warning( disable: 4232 ) /* dllimport identity*/ 29 | #pragma warning( disable: 4024 ) /* array to pointer mapping*/ 30 | #pragma warning( disable: 4152 ) /* function/data pointer conversion in expression */ 31 | #pragma warning( disable: 4100 ) /* unreferenced arguments in x86 call */ 32 | 33 | #pragma optimize("", off ) 34 | 35 | #define USE_STUBLESS_PROXY 36 | 37 | 38 | /* verify that the version is high enough to compile this file*/ 39 | #ifndef __REDQ_RPCPROXY_H_VERSION__ 40 | #define __REQUIRED_RPCPROXY_H_VERSION__ 475 41 | #endif 42 | 43 | 44 | #include "rpcproxy.h" 45 | #ifndef __RPCPROXY_H_VERSION__ 46 | #error this stub requires an updated version of 47 | #endif /* __RPCPROXY_H_VERSION__ */ 48 | 49 | 50 | #include "dia2.h" 51 | 52 | #define TYPE_FORMAT_STRING_SIZE 3 53 | #define PROC_FORMAT_STRING_SIZE 1 54 | #define EXPR_FORMAT_STRING_SIZE 1 55 | #define TRANSMIT_AS_TABLE_SIZE 0 56 | #define WIRE_MARSHAL_TABLE_SIZE 0 57 | 58 | typedef struct _dia2_MIDL_TYPE_FORMAT_STRING 59 | { 60 | short Pad; 61 | unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; 62 | } dia2_MIDL_TYPE_FORMAT_STRING; 63 | 64 | typedef struct _dia2_MIDL_PROC_FORMAT_STRING 65 | { 66 | short Pad; 67 | unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; 68 | } dia2_MIDL_PROC_FORMAT_STRING; 69 | 70 | typedef struct _dia2_MIDL_EXPR_FORMAT_STRING 71 | { 72 | long Pad; 73 | unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; 74 | } dia2_MIDL_EXPR_FORMAT_STRING; 75 | 76 | 77 | static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = 78 | {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; 79 | 80 | 81 | extern const dia2_MIDL_TYPE_FORMAT_STRING dia2__MIDL_TypeFormatString; 82 | extern const dia2_MIDL_PROC_FORMAT_STRING dia2__MIDL_ProcFormatString; 83 | extern const dia2_MIDL_EXPR_FORMAT_STRING dia2__MIDL_ExprFormatString; 84 | 85 | 86 | 87 | #if !defined(__RPC_WIN32__) 88 | #error Invalid build platform for this stub. 89 | #endif 90 | 91 | #if !(TARGET_IS_NT50_OR_LATER) 92 | #error You need Windows 2000 or later to run this stub because it uses these features: 93 | #error /robust command line switch. 94 | #error However, your C/C++ compilation flags indicate you intend to run this app on earlier systems. 95 | #error This app will fail with the RPC_X_WRONG_STUB_VERSION error. 96 | #endif 97 | 98 | 99 | static const dia2_MIDL_PROC_FORMAT_STRING dia2__MIDL_ProcFormatString = 100 | { 101 | 0, 102 | { 103 | 104 | 0x0 105 | } 106 | }; 107 | 108 | static const dia2_MIDL_TYPE_FORMAT_STRING dia2__MIDL_TypeFormatString = 109 | { 110 | 0, 111 | { 112 | NdrFcShort( 0x0 ), /* 0 */ 113 | 114 | 0x0 115 | } 116 | }; 117 | 118 | 119 | /* Standard interface: __MIDL_itf_dia2_0000_0000, ver. 0.0, 120 | GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ 121 | 122 | 123 | /* Object interface: IUnknown, ver. 0.0, 124 | GUID={0x00000000,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */ 125 | 126 | 127 | /* Object interface: IDiaLoadCallback, ver. 0.0, 128 | GUID={0xC32ADB82,0x73F4,0x421b,{0x95,0xD5,0xA4,0x70,0x6E,0xDF,0x5D,0xBE}} */ 129 | 130 | 131 | /* Object interface: IDiaLoadCallback2, ver. 0.0, 132 | GUID={0x4688a074,0x5a4d,0x4486,{0xae,0xa8,0x7b,0x90,0x71,0x1d,0x9f,0x7c}} */ 133 | 134 | 135 | /* Object interface: IDiaReadExeAtOffsetCallback, ver. 0.0, 136 | GUID={0x587A461C,0xB80B,0x4f54,{0x91,0x94,0x50,0x32,0x58,0x9A,0x63,0x19}} */ 137 | 138 | 139 | /* Object interface: IDiaReadExeAtRVACallback, ver. 0.0, 140 | GUID={0x8E3F80CA,0x7517,0x432a,{0xBA,0x07,0x28,0x51,0x34,0xAA,0xEA,0x8E}} */ 141 | 142 | 143 | /* Object interface: IDiaDataSource, ver. 0.0, 144 | GUID={0x79F1BB5F,0xB66E,0x48e5,{0xB6,0xA9,0x15,0x45,0xC3,0x23,0xCA,0x3D}} */ 145 | 146 | 147 | /* Object interface: IDiaEnumSymbols, ver. 0.0, 148 | GUID={0xCAB72C48,0x443B,0x48f5,{0x9B,0x0B,0x42,0xF0,0x82,0x0A,0xB2,0x9A}} */ 149 | 150 | 151 | /* Object interface: IDiaEnumSymbolsByAddr, ver. 0.0, 152 | GUID={0x624B7D9C,0x24EA,0x4421,{0x9D,0x06,0x3B,0x57,0x74,0x71,0xC1,0xFA}} */ 153 | 154 | 155 | /* Object interface: IDiaEnumSourceFiles, ver. 0.0, 156 | GUID={0x10F3DBD9,0x664F,0x4469,{0xB8,0x08,0x94,0x71,0xC7,0xA5,0x05,0x38}} */ 157 | 158 | 159 | /* Object interface: IDiaEnumInputAssemblyFiles, ver. 0.0, 160 | GUID={0x1C7FF653,0x51F7,0x457E,{0x84,0x19,0xB2,0x0F,0x57,0xEF,0x7E,0x4D}} */ 161 | 162 | 163 | /* Object interface: IDiaEnumLineNumbers, ver. 0.0, 164 | GUID={0xFE30E878,0x54AC,0x44f1,{0x81,0xBA,0x39,0xDE,0x94,0x0F,0x60,0x52}} */ 165 | 166 | 167 | /* Object interface: IDiaEnumInjectedSources, ver. 0.0, 168 | GUID={0xD5612573,0x6925,0x4468,{0x88,0x83,0x98,0xCD,0xEC,0x8C,0x38,0x4A}} */ 169 | 170 | 171 | /* Object interface: IDiaEnumSegments, ver. 0.0, 172 | GUID={0xE8368CA9,0x01D1,0x419d,{0xAC,0x0C,0xE3,0x12,0x35,0xDB,0xDA,0x9F}} */ 173 | 174 | 175 | /* Object interface: IDiaEnumSectionContribs, ver. 0.0, 176 | GUID={0x1994DEB2,0x2C82,0x4b1d,{0xA5,0x7F,0xAF,0xF4,0x24,0xD5,0x4A,0x68}} */ 177 | 178 | 179 | /* Object interface: IDiaEnumFrameData, ver. 0.0, 180 | GUID={0x9FC77A4B,0x3C1C,0x44ed,{0xA7,0x98,0x6C,0x1D,0xEE,0xA5,0x3E,0x1F}} */ 181 | 182 | 183 | /* Object interface: IDiaEnumDebugStreamData, ver. 0.0, 184 | GUID={0x486943E8,0xD187,0x4a6b,{0xA3,0xC4,0x29,0x12,0x59,0xFF,0xF6,0x0D}} */ 185 | 186 | 187 | /* Object interface: IDiaEnumDebugStreams, ver. 0.0, 188 | GUID={0x08CBB41E,0x47A6,0x4f87,{0x92,0xF1,0x1C,0x9C,0x87,0xCE,0xD0,0x44}} */ 189 | 190 | 191 | /* Standard interface: __MIDL_itf_dia2_0000_0016, ver. 0.0, 192 | GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ 193 | 194 | 195 | /* Object interface: IDiaAddressMap, ver. 0.0, 196 | GUID={0xB62A2E7A,0x067A,0x4ea3,{0xB5,0x98,0x04,0xC0,0x97,0x17,0x50,0x2C}} */ 197 | 198 | 199 | /* Object interface: IDiaSession, ver. 0.0, 200 | GUID={0x2F609EE1,0xD1C8,0x4E24,{0x82,0x88,0x33,0x26,0xBA,0xDC,0xD2,0x11}} */ 201 | 202 | 203 | /* Object interface: IDiaSymbol, ver. 0.0, 204 | GUID={0xcb787b2f,0xbd6c,0x4635,{0xba,0x52,0x93,0x31,0x26,0xbd,0x2d,0xcd}} */ 205 | 206 | 207 | /* Object interface: IDiaSymbol2, ver. 0.0, 208 | GUID={0x611e86cd,0xb7d1,0x4546,{0x8a,0x15,0x07,0x0e,0x2b,0x07,0xa4,0x27}} */ 209 | 210 | 211 | /* Object interface: IDiaSymbol3, ver. 0.0, 212 | GUID={0x99b665f7,0xc1b2,0x49d3,{0x89,0xb2,0xa3,0x84,0x36,0x1a,0xca,0xb5}} */ 213 | 214 | 215 | /* Object interface: IDiaSymbol4, ver. 0.0, 216 | GUID={0xbf6c88a7,0xe9d6,0x4346,{0x99,0xa1,0xd0,0x53,0xde,0x5a,0x78,0x08}} */ 217 | 218 | 219 | /* Object interface: IDiaSymbol5, ver. 0.0, 220 | GUID={0xabe2de00,0xdc2d,0x4793,{0xaf,0x9a,0xef,0x1d,0x90,0x83,0x26,0x44}} */ 221 | 222 | 223 | /* Object interface: IDiaSymbol6, ver. 0.0, 224 | GUID={0x8133dad3,0x75fe,0x4234,{0xac,0x7e,0xf8,0xe7,0xa1,0xd3,0xcb,0xb3}} */ 225 | 226 | 227 | /* Object interface: IDiaSymbol7, ver. 0.0, 228 | GUID={0x64ce6cd5,0x7315,0x4328,{0x86,0xd6,0x10,0xe3,0x03,0xe0,0x10,0xb4}} */ 229 | 230 | 231 | /* Object interface: IDiaSymbol8, ver. 0.0, 232 | GUID={0x7f2e041f,0x1294,0x41bd,{0xb8,0x3a,0xe7,0x15,0x97,0x2d,0x2c,0xe3}} */ 233 | 234 | 235 | /* Object interface: IDiaSourceFile, ver. 0.0, 236 | GUID={0xA2EF5353,0xF5A8,0x4eb3,{0x90,0xD2,0xCB,0x52,0x6A,0xCB,0x3C,0xDD}} */ 237 | 238 | 239 | /* Object interface: IDiaInputAssemblyFile, ver. 0.0, 240 | GUID={0x3BFE56B0,0x390C,0x4863,{0x94,0x30,0x1F,0x3D,0x08,0x3B,0x76,0x84}} */ 241 | 242 | 243 | /* Object interface: IDiaLineNumber, ver. 0.0, 244 | GUID={0xB388EB14,0xBE4D,0x421d,{0xA8,0xA1,0x6C,0xF7,0xAB,0x05,0x70,0x86}} */ 245 | 246 | 247 | /* Object interface: IDiaSectionContrib, ver. 0.0, 248 | GUID={0x0CF4B60E,0x35B1,0x4c6c,{0xBD,0xD8,0x85,0x4B,0x9C,0x8E,0x38,0x57}} */ 249 | 250 | 251 | /* Object interface: IDiaSegment, ver. 0.0, 252 | GUID={0x0775B784,0xC75B,0x4449,{0x84,0x8B,0xB7,0xBD,0x31,0x59,0x54,0x5B}} */ 253 | 254 | 255 | /* Object interface: IDiaInjectedSource, ver. 0.0, 256 | GUID={0xAE605CDC,0x8105,0x4a23,{0xB7,0x10,0x32,0x59,0xF1,0xE2,0x61,0x12}} */ 257 | 258 | 259 | /* Standard interface: __MIDL_itf_dia2_0000_0032, ver. 0.0, 260 | GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ 261 | 262 | 263 | /* Object interface: IDiaStackWalkFrame, ver. 0.0, 264 | GUID={0x07C590C1,0x438D,0x4F47,{0xBD,0xCD,0x43,0x97,0xBC,0x81,0xAD,0x75}} */ 265 | 266 | 267 | /* Object interface: IDiaFrameData, ver. 0.0, 268 | GUID={0xA39184B7,0x6A36,0x42de,{0x8E,0xEC,0x7D,0xF9,0xF3,0xF5,0x9F,0x33}} */ 269 | 270 | 271 | /* Object interface: IDiaImageData, ver. 0.0, 272 | GUID={0xC8E40ED2,0xA1D9,0x4221,{0x86,0x92,0x3C,0xE6,0x61,0x18,0x4B,0x44}} */ 273 | 274 | 275 | /* Object interface: IEnumUnknown, ver. 0.0, 276 | GUID={0x00000100,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}} */ 277 | 278 | 279 | /* Object interface: IDiaTable, ver. 0.0, 280 | GUID={0x4A59FB77,0xABAC,0x469b,{0xA3,0x0B,0x9E,0xCC,0x85,0xBF,0xEF,0x14}} */ 281 | 282 | 283 | /* Object interface: IDiaEnumTables, ver. 0.0, 284 | GUID={0xC65C2B0A,0x1150,0x4d7a,{0xAF,0xCC,0xE0,0x5B,0xF3,0xDE,0xE8,0x1E}} */ 285 | 286 | 287 | /* Standard interface: __MIDL_itf_dia2_0000_0038, ver. 0.0, 288 | GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ 289 | 290 | 291 | /* Object interface: IDiaPropertyStorage, ver. 0.0, 292 | GUID={0x9d416f9c,0xe184,0x45b2,{0xa4,0xf0,0xce,0x51,0x7f,0x71,0x9e,0x9b}} */ 293 | 294 | 295 | /* Object interface: IDiaStackFrame, ver. 0.0, 296 | GUID={0x5edbc96d,0xcdd6,0x4792,{0xaf,0xbe,0xcc,0x89,0x00,0x7d,0x96,0x10}} */ 297 | 298 | 299 | /* Object interface: IDiaEnumStackFrames, ver. 0.0, 300 | GUID={0xec9d461d,0xce74,0x4711,{0xa0,0x20,0x7d,0x8f,0x9a,0x1d,0xd2,0x55}} */ 301 | 302 | 303 | /* Standard interface: __MIDL_itf_dia2_0000_0041, ver. 0.0, 304 | GUID={0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} */ 305 | 306 | 307 | /* Object interface: IDiaStackWalkHelper, ver. 0.0, 308 | GUID={0x21F81B1B,0xC5BB,0x42A3,{0xBC,0x4F,0xCC,0xBA,0xA7,0x5B,0x9F,0x19}} */ 309 | 310 | 311 | /* Object interface: IDiaStackWalker, ver. 0.0, 312 | GUID={0x5485216b,0xa54c,0x469f,{0x96,0x70,0x52,0xb2,0x4d,0x52,0x29,0xbb}} */ 313 | 314 | 315 | /* Object interface: IDiaStackWalkHelper2, ver. 0.0, 316 | GUID={0x8222c490,0x507b,0x4bef,{0xb3,0xbd,0x41,0xdc,0xa7,0xb5,0x93,0x4c}} */ 317 | 318 | 319 | /* Object interface: IDiaStackWalker2, ver. 0.0, 320 | GUID={0x7c185885,0xa015,0x4cac,{0x94,0x11,0x0f,0x4f,0xb3,0x9b,0x1f,0x3a}} */ 321 | 322 | static const MIDL_STUB_DESC Object_StubDesc = 323 | { 324 | 0, 325 | NdrOleAllocate, 326 | NdrOleFree, 327 | 0, 328 | 0, 329 | 0, 330 | 0, 331 | 0, 332 | dia2__MIDL_TypeFormatString.Format, 333 | 1, /* -error bounds_check flag */ 334 | 0x50002, /* Ndr library version */ 335 | 0, 336 | 0x801026e, /* MIDL Version 8.1.622 */ 337 | 0, 338 | 0, 339 | 0, /* notify & notify_flag routine table */ 340 | 0x1, /* MIDL flag */ 341 | 0, /* cs routines */ 342 | 0, /* proxy/server info */ 343 | 0 344 | }; 345 | 346 | const CInterfaceProxyVtbl * const _dia2_ProxyVtblList[] = 347 | { 348 | 0 349 | }; 350 | 351 | const CInterfaceStubVtbl * const _dia2_StubVtblList[] = 352 | { 353 | 0 354 | }; 355 | 356 | PCInterfaceName const _dia2_InterfaceNamesList[] = 357 | { 358 | 0 359 | }; 360 | 361 | 362 | #define _dia2_CHECK_IID(n) IID_GENERIC_CHECK_IID( _dia2, pIID, n) 363 | 364 | int __stdcall _dia2_IID_Lookup( const IID * pIID, int * pIndex ) 365 | { 366 | UNREFERENCED_PARAMETER(pIID); 367 | UNREFERENCED_PARAMETER(pIndex); 368 | return 0; 369 | } 370 | 371 | const ExtendedProxyFileInfo dia2_ProxyFileInfo = 372 | { 373 | (PCInterfaceProxyVtblList *) & _dia2_ProxyVtblList, 374 | (PCInterfaceStubVtblList *) & _dia2_StubVtblList, 375 | (const PCInterfaceName * ) & _dia2_InterfaceNamesList, 376 | 0, /* no delegation */ 377 | & _dia2_IID_Lookup, 378 | 0, 379 | 2, 380 | 0, /* table of [async_uuid] interfaces */ 381 | 0, /* Filler1 */ 382 | 0, /* Filler2 */ 383 | 0 /* Filler3 */ 384 | }; 385 | #if _MSC_VER >= 1200 386 | #pragma warning(pop) 387 | #endif 388 | 389 | 390 | #endif /* !defined(_M_IA64) && !defined(_M_AMD64) && !defined(_ARM_) */ 391 | 392 | -------------------------------------------------------------------------------- /DIA_SDK/idl/dlldata.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | DllData file -- generated by MIDL compiler 3 | 4 | DO NOT ALTER THIS FILE 5 | 6 | This file is regenerated by MIDL on every IDL file compile. 7 | 8 | To completely reconstruct this file, delete it and rerun MIDL 9 | on all the IDL files in this DLL, specifying this file for the 10 | /dlldata command line option 11 | 12 | *********************************************************/ 13 | 14 | 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | EXTERN_PROXY_FILE( dia2 ) 22 | 23 | 24 | PROXYFILE_LIST_START 25 | /* Start of list */ 26 | REFERENCE_PROXY_FILE( dia2 ), 27 | /* End of list */ 28 | PROXYFILE_LIST_END 29 | 30 | 31 | DLLDATA_ROUTINES( aProxyFileList, GET_DLL_CLSID ) 32 | 33 | #ifdef __cplusplus 34 | } /*extern "C" */ 35 | #endif 36 | 37 | /* end of generated dlldata file */ 38 | -------------------------------------------------------------------------------- /DIA_SDK/idl/gen.cmd: -------------------------------------------------------------------------------- 1 | midl /I "%VSINSTALLDIR%\DIA SDK\include" "%VSINSTALLDIR%\DIA SDK\idl\dia2.idl" /tlb dia2.tlb 2 | tlbimp dia2.tlb 3 | pause 4 | -------------------------------------------------------------------------------- /DIA_SDK/include/diacreate.h: -------------------------------------------------------------------------------- 1 | // diacreate.h - creation helper functions for DIA initialization 2 | //----------------------------------------------------------------- 3 | // 4 | // Copyright Microsoft Corporation. All Rights Reserved. 5 | // 6 | //--------------------------------------------------------------- 7 | #ifndef _DIACREATE_H_ 8 | #define _DIACREATE_H_ 9 | 10 | // 11 | // Create a dia data source object from the dia dll (by dll name - does not access the registry). 12 | // 13 | 14 | HRESULT STDMETHODCALLTYPE NoRegCoCreate( const __wchar_t *dllName, 15 | REFCLSID rclsid, 16 | REFIID riid, 17 | void **ppv); 18 | 19 | #ifndef _NATIVE_WCHAR_T_DEFINED 20 | #ifdef __cplusplus 21 | 22 | HRESULT STDMETHODCALLTYPE NoRegCoCreate( const wchar_t *dllName, 23 | REFCLSID rclsid, 24 | REFIID riid, 25 | void **ppv) 26 | { 27 | return NoRegCoCreate( (const __wchar_t *)dllName, rclsid, riid, ppv ); 28 | } 29 | 30 | #endif 31 | #endif 32 | 33 | 34 | 35 | // 36 | // Create a dia data source object from the dia dll (looks up the class id in the registry). 37 | // 38 | HRESULT STDMETHODCALLTYPE NoOleCoCreate( REFCLSID rclsid, 39 | REFIID riid, 40 | void **ppv); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /DIA_SDK/lib/amd64/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/lib/amd64/diaguids.lib -------------------------------------------------------------------------------- /DIA_SDK/lib/arm/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/lib/arm/diaguids.lib -------------------------------------------------------------------------------- /DIA_SDK/lib/diaguids.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wongfei/pdb-ripper/051982b24704cca88981cd0a5a12a37fc1506af0/DIA_SDK/lib/diaguids.lib -------------------------------------------------------------------------------- /PrintSymbol.h: -------------------------------------------------------------------------------- 1 | inline int myDebugBreak( int ){ 2 | DebugBreak(); 3 | return 0; 4 | } 5 | #define MAXELEMS(x) (sizeof(x)/sizeof(x[0])) 6 | #define SafeDRef(a, i) ((i < MAXELEMS(a)) ? a[i] : a[myDebugBreak(i)]) 7 | 8 | #define MAX_TYPE_IN_DETAIL 5 9 | #define MAX_RVA_LINES_BYTES_RANGE 0x100 10 | 11 | extern const wchar_t * const rgBaseType[]; 12 | extern const wchar_t * const rgTags[]; 13 | extern const wchar_t * const rgFloatPackageStrings[]; 14 | extern const wchar_t * const rgProcessorStrings[]; 15 | extern const wchar_t * const rgDataKind[]; 16 | extern const wchar_t * const rgUdtKind[]; 17 | extern const wchar_t * const rgAccess[]; 18 | extern const wchar_t * const rgCallingConvention[]; 19 | extern const wchar_t * const rgLanguage[]; 20 | extern const wchar_t * const rgLocationTypeString[]; 21 | 22 | void PrintPublicSymbol( IDiaSymbol* ); 23 | void PrintGlobalSymbol( IDiaSymbol* ); 24 | void PrintSymbol( IDiaSymbol* , DWORD ); 25 | void PrintSymTag( DWORD ); 26 | void PrintName( IDiaSymbol* ); 27 | void PrintUndName( IDiaSymbol* ); 28 | void PrintThunk( IDiaSymbol* ); 29 | void PrintCompilandDetails( IDiaSymbol* ); 30 | void PrintCompilandEnv( IDiaSymbol* ); 31 | void PrintLocation( IDiaSymbol* ); 32 | void PrintConst( IDiaSymbol* ); 33 | void PrintUDT( IDiaSymbol* ); 34 | void PrintSymbolType( IDiaSymbol* ); 35 | void PrintType( IDiaSymbol* ); 36 | void PrintBound( IDiaSymbol* ); 37 | void PrintData( IDiaSymbol* ); 38 | void PrintVariant( VARIANT ); 39 | void PrintUdtKind( IDiaSymbol* ); 40 | void PrintTypeInDetail( IDiaSymbol* , DWORD ); 41 | void PrintFunctionType( IDiaSymbol* ); 42 | void PrintSourceFile( IDiaSourceFile* ); 43 | void PrintLines( IDiaSession* , IDiaSymbol* ); 44 | void PrintLines( IDiaEnumLineNumbers* ); 45 | void PrintSource( IDiaSourceFile* ); 46 | void PrintSecContribs( IDiaSectionContrib* ); 47 | void PrintStreamData( IDiaEnumDebugStreamData* ); 48 | void PrintFrameData( IDiaFrameData* ); 49 | 50 | void PrintPropertyStorage( IDiaPropertyStorage* ); 51 | 52 | template void PrintGeneric( T t ){ 53 | IDiaPropertyStorage* pPropertyStorage; 54 | 55 | if(t->QueryInterface( __uuidof(IDiaPropertyStorage), (void **)&pPropertyStorage ) == S_OK){ 56 | PrintPropertyStorage(pPropertyStorage); 57 | pPropertyStorage->Release(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pdb ripper 2 | 3 | Extracts UserDefinedTypes from pdb file and generates cpp code 4 | 5 | ## Usage 6 | 7 | ``` 8 | Dia2Dump.exe -rip [flags] ... 9 | -printNamesOnly 10 | -printCppProxy 11 | -genCppFiles 12 | -ii : include internals 13 | -it : include templates 14 | -s : generate symbol information 15 | -m : generate meta information 16 | -d : include deps 17 | -rd : resolve/sort deps 18 | -names : select specific UDTs (-names "nameA;nameB;-excludeC") 19 | ``` 20 | 21 | ## How it works 22 | 23 | Imagine some code compiled into test.exe / test.pdb 24 | 25 | ```cpp 26 | class Shape { 27 | public: 28 | Shape(int newx, int newy); 29 | virtual ~Shape(); 30 | int getX(); 31 | int getY(); 32 | void setX(int newx); 33 | void setY(int newy); 34 | void moveTo(int newx, int newy); 35 | void rMoveTo(int deltax, int deltay); 36 | virtual void draw(); 37 | private: 38 | int x; 39 | int y; 40 | }; 41 | 42 | Shape::Shape(int newx, int newy) { moveTo(newx, newy); } 43 | Shape::~Shape() {} 44 | int Shape::getX() { return x; } 45 | int Shape::getY() { return y; } 46 | void Shape::setX(int newx) { x = newx; } 47 | void Shape::setY(int newy) { y = newy; } 48 | void Shape::moveTo(int newx, int newy) { setX(newx); setY(newy); } 49 | void Shape::rMoveTo(int deltax, int deltay) { moveTo(getX() + deltax, getY() + deltay); } 50 | void Shape::draw() {} 51 | 52 | class Rectangle: public Shape { 53 | public: 54 | Rectangle(int newx, int newy, int newwidth, int newheight); 55 | int getWidth(); 56 | int getHeight(); 57 | void setWidth(int newwidth); 58 | void setHeight(int newheight); 59 | void draw(); 60 | private: 61 | int width; 62 | int height; 63 | }; 64 | 65 | Rectangle::Rectangle(int newx, int newy, int newwidth, int newheight): Shape(newx, newy) { setWidth(newwidth); setHeight(newheight); } 66 | int Rectangle::getWidth() { return width; } 67 | int Rectangle::getHeight() { return height; } 68 | void Rectangle::setWidth(int newwidth) { width = newwidth; } 69 | void Rectangle::setHeight(int newheight) { height = newheight; } 70 | void Rectangle::draw() { printf("Rectangle %d %d %d %d\n", getX(), getY(), getWidth(), getHeight()); } 71 | 72 | class Circle: public Shape { 73 | public: 74 | Circle(int newx, int newy, int newradius); 75 | int getRadius(); 76 | void setRadius(int newradius); 77 | void draw(); 78 | private: 79 | int radius; 80 | }; 81 | 82 | Circle::Circle(int newx, int newy, int newradius): Shape(newx, newy) { setRadius(newradius); } 83 | int Circle::getRadius() { return radius; } 84 | void Circle::setRadius(int newradius) { radius = newradius; } 85 | void Circle::draw() { printf("Circle %d %d %d\n", getX(), getY(), getRadius()); } 86 | ``` 87 | 88 | Invite the ripper to do some work: 89 | 90 | `Dia2Dump.exe -rip -printCppProxy -s -m -d -rd -names "Rectangle;Circle" test.pdb > gen.h` 91 | 92 | Generated file: 93 | 94 | ```cpp 95 | //UDT: class Shape @len=16 @vfcount=2 96 | //_VTable: 97 | //_Func: public void Shape(Shape & _arg0); @loc=optimized @len=0 @rva=0 98 | //_Func: public void Shape(int newx, int newy); @loc=static @len=62 @rva=6768 99 | //_Func: public void ~Shape(); @intro @virtual vtpo=0 vfid=0 @loc=static @len=21 @rva=7664 100 | //_Func: public int getX(); @loc=static @len=14 @rva=14208 101 | //_Func: public int getY(); @loc=static @len=14 @rva=14224 102 | //_Func: public void setX(int newx); @loc=static @len=22 @rva=14960 103 | //_Func: public void setY(int newy); @loc=static @len=22 @rva=14992 104 | //_Func: public void moveTo(int newx, int newy); @loc=static @len=51 @rva=14720 105 | //_Func: public void rMoveTo(int deltax, int deltay); @loc=static @len=74 @rva=14784 106 | //_Func: public void draw(); @intro @virtual vtpo=0 vfid=1 @loc=static @len=6 @rva=13808 107 | //_Data: this+0x8, Member, Type: int, x 108 | //_Data: this+0xC, Member, Type: int, y 109 | //_Func: public Shape & operator=(Shape & _arg0); @loc=optimized @len=0 @rva=0 110 | //_Func: public void * __vecDelDtor(unsigned int _arg0); @intro @virtual vtpo=0 vfid=0 @loc=optimized @len=0 @rva=0 111 | //UDT; 112 | 113 | class Shape { 114 | public: 115 | int x; 116 | int y; 117 | inline Shape() { } 118 | inline void ctor(int newx, int newy) { typedef void (*_fpt)(Shape *pthis, int, int); _fpt _f=(_fpt)_drva(6768); _f(this, newx, newy); } 119 | virtual ~Shape(); 120 | inline void dtor() { typedef void (*_fpt)(Shape *pthis); _fpt _f=(_fpt)_drva(7664); _f(this); } 121 | inline int getX() { typedef int (*_fpt)(Shape *pthis); _fpt _f=(_fpt)_drva(14208); return _f(this); } 122 | inline int getY() { typedef int (*_fpt)(Shape *pthis); _fpt _f=(_fpt)_drva(14224); return _f(this); } 123 | inline void setX(int newx) { typedef void (*_fpt)(Shape *pthis, int); _fpt _f=(_fpt)_drva(14960); return _f(this, newx); } 124 | inline void setY(int newy) { typedef void (*_fpt)(Shape *pthis, int); _fpt _f=(_fpt)_drva(14992); return _f(this, newy); } 125 | inline void moveTo(int newx, int newy) { typedef void (*_fpt)(Shape *pthis, int, int); _fpt _f=(_fpt)_drva(14720); return _f(this, newx, newy); } 126 | inline void rMoveTo(int deltax, int deltay) { typedef void (*_fpt)(Shape *pthis, int, int); _fpt _f=(_fpt)_drva(14784); return _f(this, deltax, deltay); } 127 | virtual void draw_vf1(); 128 | inline void draw_impl() { typedef void (*_fpt)(Shape *pthis); _fpt _f=(_fpt)_drva(13808); return _f(this); } 129 | inline void draw() { return draw_vf1(); } 130 | }; 131 | 132 | //UDT: class Rectangle @len=24 @vfcount=2 133 | //_Base: class Shape @off=0 @len=16 134 | //_Func: public void Rectangle(Rectangle * _arg0); @loc=optimized @len=0 @rva=0 135 | //_Func: public void Rectangle(Rectangle & _arg0); @loc=optimized @len=0 @rva=0 136 | //_Func: public void Rectangle(int newx, int newy, int newwidth, int newheight); @loc=static @len=106 @rva=6656 137 | //_Func: public int getWidth(); @loc=static @len=14 @rva=14192 138 | //_Func: public int getHeight(); @loc=static @len=14 @rva=14160 139 | //_Func: public void setWidth(int newwidth); @loc=static @len=22 @rva=14928 140 | //_Func: public void setHeight(int newheight); @loc=static @len=22 @rva=14864 141 | //_Func: public void draw(); @virtual vtpo=0 vfid=1 @loc=static @len=102 @rva=13696 142 | //_Data: this+0x10, Member, Type: int, width 143 | //_Data: this+0x14, Member, Type: int, height 144 | //_Func: public void ~Rectangle(); @virtual vtpo=0 vfid=0 @loc=static @len=24 @rva=7632 145 | //_Func: public Rectangle & operator=(Rectangle * _arg0); @loc=optimized @len=0 @rva=0 146 | //_Func: public Rectangle & operator=(Rectangle & _arg0); @loc=optimized @len=0 @rva=0 147 | //_Func: public void * __vecDelDtor(unsigned int _arg0); @intro @virtual vtpo=0 vfid=0 @loc=optimized @len=0 @rva=0 148 | //UDT; 149 | 150 | class Rectangle : public Shape { 151 | public: 152 | int width; 153 | int height; 154 | inline Rectangle() { } 155 | inline void ctor(int newx, int newy, int newwidth, int newheight) { typedef void (*_fpt)(Rectangle *pthis, int, int, int, int); _fpt _f=(_fpt)_drva(6656); _f(this, newx, newy, newwidth, newheight); } 156 | inline int getWidth() { typedef int (*_fpt)(Rectangle *pthis); _fpt _f=(_fpt)_drva(14192); return _f(this); } 157 | inline int getHeight() { typedef int (*_fpt)(Rectangle *pthis); _fpt _f=(_fpt)_drva(14160); return _f(this); } 158 | inline void setWidth(int newwidth) { typedef void (*_fpt)(Rectangle *pthis, int); _fpt _f=(_fpt)_drva(14928); return _f(this, newwidth); } 159 | inline void setHeight(int newheight) { typedef void (*_fpt)(Rectangle *pthis, int); _fpt _f=(_fpt)_drva(14864); return _f(this, newheight); } 160 | virtual void draw_vf1(); 161 | inline void draw_impl() { typedef void (*_fpt)(Rectangle *pthis); _fpt _f=(_fpt)_drva(13696); return _f(this); } 162 | inline void draw() { return draw_vf1(); } 163 | virtual ~Rectangle(); 164 | inline void dtor() { typedef void (*_fpt)(Rectangle *pthis); _fpt _f=(_fpt)_drva(7632); _f(this); } 165 | }; 166 | 167 | //UDT: class Circle @len=24 @vfcount=2 168 | //_Base: class Shape @off=0 @len=16 169 | //_Func: public void Circle(Circle * _arg0); @loc=optimized @len=0 @rva=0 170 | //_Func: public void Circle(Circle & _arg0); @loc=optimized @len=0 @rva=0 171 | //_Func: public void Circle(int newx, int newy, int newradius); @loc=static @len=92 @rva=5856 172 | //_Func: public int getRadius(); @loc=static @len=14 @rva=14176 173 | //_Func: public void setRadius(int newradius); @loc=static @len=22 @rva=14896 174 | //_Func: public void draw(); @virtual vtpo=0 vfid=1 @loc=static @len=80 @rva=13616 175 | //_Data: this+0x10, Member, Type: int, radius 176 | //_Func: public void ~Circle(); @virtual vtpo=0 vfid=0 @loc=static @len=24 @rva=7152 177 | //_Func: public Circle & operator=(Circle * _arg0); @loc=optimized @len=0 @rva=0 178 | //_Func: public Circle & operator=(Circle & _arg0); @loc=optimized @len=0 @rva=0 179 | //_Func: public void * __vecDelDtor(unsigned int _arg0); @intro @virtual vtpo=0 vfid=0 @loc=optimized @len=0 @rva=0 180 | //UDT; 181 | 182 | class Circle : public Shape { 183 | public: 184 | int radius; 185 | inline Circle() { } 186 | inline void ctor(int newx, int newy, int newradius) { typedef void (*_fpt)(Circle *pthis, int, int, int); _fpt _f=(_fpt)_drva(5856); _f(this, newx, newy, newradius); } 187 | inline int getRadius() { typedef int (*_fpt)(Circle *pthis); _fpt _f=(_fpt)_drva(14176); return _f(this); } 188 | inline void setRadius(int newradius) { typedef void (*_fpt)(Circle *pthis, int); _fpt _f=(_fpt)_drva(14896); return _f(this, newradius); } 189 | virtual void draw_vf1(); 190 | inline void draw_impl() { typedef void (*_fpt)(Circle *pthis); _fpt _f=(_fpt)_drva(13616); return _f(this); } 191 | inline void draw() { return draw_vf1(); } 192 | virtual ~Circle(); 193 | inline void dtor() { typedef void (*_fpt)(Circle *pthis); _fpt _f=(_fpt)_drva(7152); _f(this); } 194 | }; 195 | ``` 196 | 197 | Inject into test.exe and do some manipulations: 198 | 199 | ```cpp 200 | template 201 | static inline T* new_udt(Args&&... params) { 202 | T* obj = (T*)malloc(sizeof(T)); 203 | obj->ctor(std::forward(params)...); 204 | return obj; 205 | } 206 | 207 | Circle* obj = new_udt(0, 0, 10); 208 | obj->draw(); 209 | ``` 210 | -------------------------------------------------------------------------------- /dia2dump.cpp: -------------------------------------------------------------------------------- 1 | // Dia2Dump.cpp : Defines the entry point for the console application. 2 | // 3 | // This is a part of the Debug Interface Access SDK 4 | // Copyright (c) Microsoft Corporation. All rights reserved. 5 | // 6 | // This source code is only intended as a supplement to the 7 | // Debug Interface Access SDK and related electronic documentation 8 | // provided with the library. 9 | // See these sources for detailed information regarding the 10 | // Debug Interface Access SDK API. 11 | // 12 | 13 | #include "stdafx.h" 14 | #include "Dia2Dump.h" 15 | #include "PrintSymbol.h" 16 | 17 | #include "Callback.h" 18 | 19 | #pragma warning (disable : 4100) 20 | 21 | const wchar_t *g_szFilename; 22 | IDiaDataSource *g_pDiaDataSource; 23 | IDiaSession *g_pDiaSession; 24 | IDiaSymbol *g_pGlobalSymbol; 25 | DWORD g_dwMachineType = CV_CFL_80386; 26 | 27 | extern void RipPdb(IDiaSymbol *pGlobal, int argc, wchar_t *argv[]); 28 | 29 | //////////////////////////////////////////////////////////// 30 | // 31 | int wmain(int argc, wchar_t *argv[]) 32 | { 33 | FILE *pFile; 34 | 35 | if (argc < 2) { 36 | PrintHelpOptions(); 37 | return -1; 38 | } 39 | 40 | if (_wfopen_s(&pFile, argv[argc - 1], L"r") || !pFile) { 41 | // invalid file name or file does not exist 42 | 43 | PrintHelpOptions(); 44 | return -1; 45 | } 46 | 47 | fclose(pFile); 48 | 49 | g_szFilename = argv[argc - 1]; 50 | 51 | // CoCreate() and initialize COM objects 52 | 53 | if (!LoadDataFromPdb(g_szFilename, &g_pDiaDataSource, &g_pDiaSession, &g_pGlobalSymbol)) { 54 | return -1; 55 | } 56 | 57 | if (argc == 2) { 58 | // no options passed; print all pdb info 59 | 60 | DumpAllPdbInfo(g_pDiaSession, g_pGlobalSymbol); 61 | } 62 | 63 | else if (!_wcsicmp(argv[1], L"-all")) { 64 | DumpAllPdbInfo(g_pDiaSession, g_pGlobalSymbol); 65 | } 66 | 67 | else if (!_wcsicmp(argv[1], L"-rip")) { 68 | RipPdb(g_pGlobalSymbol, argc, argv); 69 | } 70 | 71 | else if (!ParseArg(argc-2, &argv[1])) { 72 | Cleanup(); 73 | 74 | return -1; 75 | } 76 | 77 | // release COM objects and CoUninitialize() 78 | 79 | Cleanup(); 80 | 81 | return 0; 82 | } 83 | 84 | //////////////////////////////////////////////////////////// 85 | // Create an IDiaData source and open a PDB file 86 | // 87 | bool LoadDataFromPdb( 88 | const wchar_t *szFilename, 89 | IDiaDataSource **ppSource, 90 | IDiaSession **ppSession, 91 | IDiaSymbol **ppGlobal) 92 | { 93 | wchar_t wszExt[MAX_PATH]; 94 | wchar_t *wszSearchPath = L"SRV**\\\\symbols\\symbols"; // Alternate path to search for debug data 95 | DWORD dwMachType = 0; 96 | 97 | HRESULT hr = CoInitialize(NULL); 98 | 99 | // Obtain access to the provider 100 | 101 | hr = CoCreateInstance(__uuidof(DiaSource), 102 | NULL, 103 | CLSCTX_INPROC_SERVER, 104 | __uuidof(IDiaDataSource), 105 | (void **) ppSource); 106 | 107 | if (FAILED(hr)) { 108 | wprintf(L"CoCreateInstance failed - HRESULT = %08X\n", hr); 109 | 110 | return false; 111 | } 112 | 113 | _wsplitpath_s(szFilename, NULL, 0, NULL, 0, NULL, 0, wszExt, MAX_PATH); 114 | 115 | if (!_wcsicmp(wszExt, L".pdb")) { 116 | // Open and prepare a program database (.pdb) file as a debug data source 117 | 118 | hr = (*ppSource)->loadDataFromPdb(szFilename); 119 | 120 | if (FAILED(hr)) { 121 | wprintf(L"loadDataFromPdb failed - HRESULT = %08X\n", hr); 122 | 123 | return false; 124 | } 125 | } 126 | 127 | else { 128 | CCallback callback; // Receives callbacks from the DIA symbol locating procedure, 129 | // thus enabling a user interface to report on the progress of 130 | // the location attempt. The client application may optionally 131 | // provide a reference to its own implementation of this 132 | // virtual base class to the IDiaDataSource::loadDataForExe method. 133 | callback.AddRef(); 134 | 135 | // Open and prepare the debug data associated with the executable 136 | 137 | hr = (*ppSource)->loadDataForExe(szFilename, wszSearchPath, &callback); 138 | 139 | if (FAILED(hr)) { 140 | wprintf(L"loadDataForExe failed - HRESULT = %08X\n", hr); 141 | 142 | return false; 143 | } 144 | } 145 | 146 | // Open a session for querying symbols 147 | 148 | hr = (*ppSource)->openSession(ppSession); 149 | 150 | if (FAILED(hr)) { 151 | wprintf(L"openSession failed - HRESULT = %08X\n", hr); 152 | 153 | return false; 154 | } 155 | 156 | // Retrieve a reference to the global scope 157 | 158 | hr = (*ppSession)->get_globalScope(ppGlobal); 159 | 160 | if (hr != S_OK) { 161 | wprintf(L"get_globalScope failed\n"); 162 | 163 | return false; 164 | } 165 | 166 | // Set Machine type for getting correct register names 167 | 168 | if ((*ppGlobal)->get_machineType(&dwMachType) == S_OK) { 169 | switch (dwMachType) { 170 | case IMAGE_FILE_MACHINE_I386 : g_dwMachineType = CV_CFL_80386; break; 171 | case IMAGE_FILE_MACHINE_IA64 : g_dwMachineType = CV_CFL_IA64; break; 172 | case IMAGE_FILE_MACHINE_AMD64 : g_dwMachineType = CV_CFL_AMD64; break; 173 | } 174 | } 175 | 176 | return true; 177 | } 178 | 179 | //////////////////////////////////////////////////////////// 180 | // Release DIA objects and CoUninitialize 181 | // 182 | void Cleanup() 183 | { 184 | if (g_pGlobalSymbol) { 185 | g_pGlobalSymbol->Release(); 186 | g_pGlobalSymbol = NULL; 187 | } 188 | 189 | if (g_pDiaSession) { 190 | g_pDiaSession->Release(); 191 | g_pDiaSession = NULL; 192 | } 193 | 194 | CoUninitialize(); 195 | } 196 | 197 | //////////////////////////////////////////////////////////// 198 | // Parse the arguments of the program 199 | // 200 | bool ParseArg(int argc, wchar_t *argv[]) 201 | { 202 | int iCount = 0; 203 | bool bReturn = true; 204 | 205 | if (!argc) { 206 | return true; 207 | } 208 | 209 | if (!_wcsicmp(argv[0], L"-?")) { 210 | PrintHelpOptions(); 211 | 212 | return true; 213 | } 214 | 215 | else if (!_wcsicmp(argv[0], L"-help")) { 216 | PrintHelpOptions(); 217 | 218 | return true; 219 | } 220 | 221 | else if (!_wcsicmp(argv[0], L"-m")) { 222 | // -m : print all the mods 223 | 224 | iCount = 1; 225 | bReturn = bReturn && DumpAllMods(g_pGlobalSymbol); 226 | argc -= iCount; 227 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 228 | } 229 | 230 | else if (!_wcsicmp(argv[0], L"-p")) { 231 | // -p : print all the publics 232 | 233 | iCount = 1; 234 | bReturn = bReturn && DumpAllPublics(g_pGlobalSymbol); 235 | argc -= iCount; 236 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 237 | } 238 | 239 | else if (!_wcsicmp(argv[0], L"-s")) { 240 | // -s : print symbols 241 | 242 | iCount = 1; 243 | bReturn = bReturn && DumpAllSymbols(g_pGlobalSymbol); 244 | argc -= iCount; 245 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 246 | } 247 | 248 | else if (!_wcsicmp(argv[0], L"-g")) { 249 | // -g : print all the globals 250 | 251 | iCount = 1; 252 | bReturn = bReturn && DumpAllGlobals(g_pGlobalSymbol); 253 | argc -= iCount; 254 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 255 | } 256 | 257 | else if (!_wcsicmp(argv[0], L"-t")) { 258 | // -t : print all the types 259 | 260 | iCount = 1; 261 | bReturn = bReturn && DumpAllTypes(g_pGlobalSymbol); 262 | argc -= iCount; 263 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 264 | } 265 | 266 | else if (!_wcsicmp(argv[0], L"-f")) { 267 | // -f : print all the files 268 | 269 | iCount = 1; 270 | bReturn = bReturn && DumpAllFiles(g_pDiaSession, g_pGlobalSymbol); 271 | argc -= iCount; 272 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 273 | } 274 | 275 | else if (!_wcsicmp(argv[0], L"-l")) { 276 | if (argc > 1 && *argv[1] != L'-') { 277 | // -l RVA [bytes] : print line number info at RVA address in the bytes range 278 | 279 | DWORD dwRVA = 0; 280 | DWORD dwRange = MAX_RVA_LINES_BYTES_RANGE; 281 | 282 | swscanf_s(argv[1], L"%x", &dwRVA); 283 | if (argc > 2 && *argv[2] != L'-') { 284 | swscanf_s(argv[2], L"%d", &dwRange); 285 | iCount = 3; 286 | } 287 | 288 | else { 289 | iCount = 2; 290 | } 291 | 292 | bReturn = bReturn && DumpAllLines(g_pDiaSession, dwRVA, dwRange); 293 | } 294 | 295 | else { 296 | // -l : print line number info 297 | 298 | bReturn = bReturn && DumpAllLines(g_pDiaSession, g_pGlobalSymbol); 299 | iCount = 1; 300 | } 301 | 302 | argc -= iCount; 303 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 304 | } 305 | 306 | else if (!_wcsicmp(argv[0], L"-c")) { 307 | // -c : print section contribution info 308 | 309 | iCount = 1; 310 | bReturn = bReturn && DumpAllSecContribs(g_pDiaSession); 311 | argc -= iCount; 312 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 313 | } 314 | 315 | else if (!_wcsicmp(argv[0], L"-dbg")) { 316 | // -dbg : dump debug streams 317 | 318 | iCount = 1; 319 | bReturn = bReturn && DumpAllDebugStreams(g_pDiaSession); 320 | argc -= iCount; 321 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 322 | } 323 | 324 | else if (!_wcsicmp(argv[0], L"-injsrc")) { 325 | if (argc > 1 && *argv[1] != L'-') { 326 | // -injsrc filename : dump injected source filename 327 | 328 | bReturn = bReturn && DumpInjectedSource(g_pDiaSession, argv[1]); 329 | iCount = 2; 330 | } 331 | 332 | else { 333 | // -injsrc : dump all injected source 334 | 335 | bReturn = bReturn && DumpAllInjectedSources(g_pDiaSession); 336 | iCount = 1; 337 | } 338 | 339 | argc -= iCount; 340 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 341 | } 342 | 343 | else if (!_wcsicmp(argv[0], L"-sf")) { 344 | // -sf : dump all source files 345 | 346 | iCount = 1; 347 | bReturn = bReturn && DumpAllSourceFiles(g_pDiaSession, g_pGlobalSymbol); 348 | argc -= iCount; 349 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 350 | } 351 | 352 | else if (!_wcsicmp(argv[0], L"-oem")) { 353 | // -oem : dump all OEM specific types 354 | 355 | iCount = 1; 356 | bReturn = bReturn && DumpAllOEMs(g_pGlobalSymbol); 357 | argc -= iCount; 358 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 359 | } 360 | 361 | else if (!_wcsicmp(argv[0], L"-fpo")) { 362 | if (argc > 1 && *argv[1] != L'-') { 363 | DWORD dwRVA = 0; 364 | 365 | if (iswdigit(*argv[1])) { 366 | // -fpo [RVA] : dump frame pointer omission information for a function address 367 | 368 | swscanf_s(argv[1], L"%x", &dwRVA); 369 | bReturn = bReturn && DumpFPO(g_pDiaSession, dwRVA); 370 | } 371 | 372 | else { 373 | // -fpo [symbolname] : dump frame pointer omission information for a function symbol 374 | 375 | bReturn = bReturn && DumpFPO(g_pDiaSession, g_pGlobalSymbol, argv[1]); 376 | } 377 | 378 | iCount = 2; 379 | } 380 | 381 | else { 382 | bReturn = bReturn && DumpAllFPO(g_pDiaSession); 383 | iCount = 1; 384 | } 385 | 386 | argc -= iCount; 387 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 388 | } 389 | 390 | else if (!_wcsicmp(argv[0], L"-compiland")) { 391 | if ((argc > 1) && (*argv[1] != L'-')) { 392 | // -compiland [name] : dump symbols for this compiland 393 | 394 | bReturn = bReturn && DumpCompiland(g_pGlobalSymbol, argv[1]); 395 | argc -= 2; 396 | } 397 | 398 | else { 399 | wprintf(L"ERROR - ParseArg(): missing argument for option '-line'"); 400 | 401 | return false; 402 | } 403 | 404 | argc -= iCount; 405 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 406 | } 407 | 408 | else if (!_wcsicmp(argv[0], L"-lines")) { 409 | if ((argc > 1) && (*argv[1] != L'-')) { 410 | DWORD dwRVA = 0; 411 | 412 | if (iswdigit(*argv[1])) { 413 | // -lines : dump line numbers for this address\n" 414 | 415 | swscanf_s(argv[1], L"%x", &dwRVA); 416 | bReturn = bReturn && DumpLines(g_pDiaSession, dwRVA); 417 | } 418 | 419 | else { 420 | // -lines : dump line numbers for this function 421 | 422 | bReturn = bReturn && DumpLines(g_pDiaSession, g_pGlobalSymbol, argv[1]); 423 | } 424 | 425 | iCount = 2; 426 | } 427 | 428 | else { 429 | wprintf(L"ERROR - ParseArg(): missing argument for option '-compiland'"); 430 | 431 | return false; 432 | } 433 | 434 | argc -= iCount; 435 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 436 | } 437 | 438 | else if (!_wcsicmp(argv[0], L"-type")) { 439 | // -type : dump this type in detail 440 | 441 | if ((argc > 1) && (*argv[1] != L'-')) { 442 | bReturn = bReturn && DumpType(g_pGlobalSymbol, argv[1]); 443 | iCount = 2; 444 | } 445 | 446 | else { 447 | wprintf(L"ERROR - ParseArg(): missing argument for option '-type'"); 448 | 449 | return false; 450 | } 451 | 452 | argc -= iCount; 453 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 454 | } 455 | 456 | else if (!_wcsicmp(argv[0], L"-label")) { 457 | // -label : dump label at RVA 458 | if ((argc > 1) && (*argv[1] != L'-')) { 459 | DWORD dwRVA = 0; 460 | 461 | swscanf_s(argv[1], L"%x", &dwRVA); 462 | bReturn = bReturn && DumpLabel(g_pDiaSession, dwRVA); 463 | iCount = 2; 464 | } 465 | 466 | else { 467 | wprintf(L"ERROR - ParseArg(): missing argument for option '-label'"); 468 | 469 | return false; 470 | } 471 | 472 | argc -= iCount; 473 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 474 | } 475 | 476 | else if (!_wcsicmp(argv[0], L"-sym")) { 477 | if ((argc > 1) && (*argv[1] != L'-')) { 478 | DWORD dwRVA = 0; 479 | const wchar_t *szChildname = NULL; 480 | 481 | iCount = 2; 482 | 483 | if (argc > 2 && *argv[2] != L'-') { 484 | szChildname = argv[2]; 485 | iCount = 3; 486 | } 487 | 488 | if (iswdigit(*argv[1])) { 489 | // -sym [childname] : dump child information of symbol at this address 490 | 491 | swscanf_s(argv[1], L"%x", &dwRVA); 492 | bReturn = bReturn && DumpSymbolWithRVA(g_pDiaSession, dwRVA, szChildname); 493 | } 494 | 495 | else { 496 | // -sym [childname] : dump child information of this symbol 497 | 498 | bReturn = bReturn && DumpSymbolsWithRegEx(g_pGlobalSymbol, argv[1], szChildname); 499 | } 500 | } 501 | 502 | else { 503 | wprintf(L"ERROR - ParseArg(): missing argument for option '-sym'"); 504 | 505 | return false; 506 | } 507 | 508 | argc -= iCount; 509 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 510 | } 511 | 512 | else if (!_wcsicmp(argv[0], L"-lsrc")) { 513 | // -lsrc [line] : dump line numbers for this source file 514 | 515 | if ((argc > 1) && (*argv[1] != L'-')) { 516 | DWORD dwLine = 0; 517 | 518 | iCount = 2; 519 | if (argc > 2 && *argv[2] != L'-') { 520 | swscanf_s(argv[1], L"%d", &dwLine); 521 | iCount = 3; 522 | } 523 | 524 | bReturn = bReturn && DumpLinesForSourceFile(g_pDiaSession, argv[1], dwLine); 525 | } 526 | 527 | else { 528 | wprintf(L"ERROR - ParseArg(): missing argument for option '-lsrc'"); 529 | 530 | return false; 531 | } 532 | 533 | argc -= iCount; 534 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 535 | } 536 | 537 | else if (!_wcsicmp(argv[0], L"-ps")) { 538 | // -ps [-n ] : dump symbols after this address, default 16 539 | 540 | if ((argc > 1) && (*argv[1] != L'-')) { 541 | DWORD dwRVA = 0; 542 | DWORD dwRange; 543 | 544 | swscanf_s(argv[1], L"%x", &dwRVA); 545 | if (argc > 3 && !_wcsicmp(argv[2], L"-n")) { 546 | swscanf_s(argv[3], L"%d", &dwRange); 547 | iCount = 4; 548 | } 549 | 550 | else { 551 | dwRange = 16; 552 | iCount = 2; 553 | } 554 | 555 | bReturn = bReturn && DumpPublicSymbolsSorted(g_pDiaSession, dwRVA, dwRange, true); 556 | } 557 | 558 | else { 559 | wprintf(L"ERROR - ParseArg(): missing argument for option '-ps'"); 560 | 561 | return false; 562 | } 563 | 564 | argc -= iCount; 565 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 566 | } 567 | 568 | else if (!_wcsicmp(argv[0], L"-psr")) { 569 | // -psr [-n ] : dump symbols before this address, default 16 570 | 571 | if ((argc > 1) && (*argv[1] != L'-')) { 572 | DWORD dwRVA = 0; 573 | DWORD dwRange; 574 | 575 | swscanf_s(argv[1], L"%x", &dwRVA); 576 | 577 | if (argc > 3 && !_wcsicmp(argv[2], L"-n")) { 578 | swscanf_s(argv[3], L"%d", &dwRange); 579 | iCount = 4; 580 | } 581 | 582 | else { 583 | dwRange = 16; 584 | iCount = 2; 585 | } 586 | 587 | bReturn = bReturn && DumpPublicSymbolsSorted(g_pDiaSession, dwRVA, dwRange, false); 588 | } 589 | 590 | else { 591 | wprintf(L"ERROR - ParseArg(): missing argument for option '-psr'"); 592 | 593 | return false; 594 | } 595 | 596 | argc -= iCount; 597 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 598 | } 599 | 600 | else if (!_wcsicmp(argv[0], L"-annotations")) { 601 | // -annotations : dump annotation symbol for this RVA 602 | 603 | if ((argc > 1) && (*argv[1] != L'-')) { 604 | DWORD dwRVA = 0; 605 | 606 | swscanf_s(argv[1], L"%x", &dwRVA); 607 | bReturn = bReturn && DumpAnnotations(g_pDiaSession, dwRVA); 608 | iCount = 2; 609 | } 610 | 611 | else { 612 | wprintf(L"ERROR - ParseArg(): missing argument for option '-maptosrc'"); 613 | 614 | return false; 615 | } 616 | 617 | argc -= iCount; 618 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 619 | } 620 | 621 | else if (!_wcsicmp(argv[0], L"-maptosrc")) { 622 | // -maptosrc : dump src RVA for this image RVA 623 | 624 | if ((argc > 1) && (*argv[1] != L'-')) { 625 | DWORD dwRVA = 0; 626 | 627 | swscanf_s(argv[1], L"%x", &dwRVA); 628 | bReturn = bReturn && DumpMapToSrc(g_pDiaSession, dwRVA); 629 | iCount = 2; 630 | } 631 | 632 | else { 633 | wprintf(L"ERROR - ParseArg(): missing argument for option '-maptosrc'"); 634 | 635 | return false; 636 | } 637 | 638 | argc -= iCount; 639 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 640 | } 641 | 642 | else if (!_wcsicmp(argv[0], L"-mapfromsrc")) { 643 | // -mapfromsrc : dump image RVA for src RVA 644 | 645 | if ((argc > 1) && (*argv[1] != L'-')) { 646 | DWORD dwRVA = 0; 647 | 648 | swscanf_s(argv[1], L"%x", &dwRVA); 649 | bReturn = bReturn && DumpMapFromSrc(g_pDiaSession, dwRVA); 650 | iCount = 2; 651 | } 652 | 653 | else { 654 | wprintf(L"ERROR - ParseArg(): missing argument for option '-mapfromsrc'"); 655 | 656 | return false; 657 | } 658 | 659 | argc -= iCount; 660 | bReturn = bReturn && ParseArg(argc, &argv[iCount]); 661 | } 662 | 663 | else { 664 | wprintf(L"ERROR - unknown option %s\n", argv[0]); 665 | 666 | PrintHelpOptions(); 667 | 668 | return false; 669 | } 670 | 671 | return bReturn; 672 | } 673 | 674 | //////////////////////////////////////////////////////////// 675 | // Display the usage 676 | // 677 | void PrintHelpOptions() 678 | { 679 | static const wchar_t * const helpString = L"usage: Dia2Dump.exe [ options ] \n" 680 | L" -? : print this help\n" 681 | L" -all : print all the debug info\n" 682 | L" -m : print all the mods\n" 683 | L" -p : print all the publics\n" 684 | L" -g : print all the globals\n" 685 | L" -t : print all the types\n" 686 | L" -f : print all the files\n" 687 | L" -s : print symbols\n" 688 | L" -l [RVA [bytes]] : print line number info at RVA address in the bytes range\n" 689 | L" -c : print section contribution info\n" 690 | L" -dbg : dump debug streams\n" 691 | L" -injsrc [file] : dump injected source\n" 692 | L" -sf : dump all source files\n" 693 | L" -oem : dump all OEM specific types\n" 694 | L" -fpo [RVA] : dump frame pointer omission information for a func addr\n" 695 | L" -fpo [symbolname] : dump frame pointer omission information for a func symbol\n" 696 | L" -compiland [name] : dump symbols for this compiland\n" 697 | L" -lines : dump line numbers for this function\n" 698 | L" -lines : dump line numbers for this address\n" 699 | L" -type : dump this type in detail\n" 700 | L" -label : dump label at RVA\n" 701 | L" -sym [childname] : dump child information of this symbol\n" 702 | L" -sym [childname] : dump child information of symbol at this addr\n" 703 | L" -lsrc [line] : dump line numbers for this source file\n" 704 | L" -ps [-n ] : dump symbols after this address, default 16\n" 705 | L" -psr [-n ] : dump symbols before this address, default 16\n" 706 | L" -annotations : dump annotation symbol for this RVA\n" 707 | L" -maptosrc : dump src RVA for this image RVA\n" 708 | L" -mapfromsrc : dump image RVA for src RVA\n"; 709 | 710 | wprintf(helpString); 711 | } 712 | 713 | //////////////////////////////////////////////////////////// 714 | // Dump all the data stored in a PDB 715 | // 716 | void DumpAllPdbInfo(IDiaSession *pSession, IDiaSymbol *pGlobal) 717 | { 718 | DumpAllMods(pGlobal); 719 | DumpAllPublics(pGlobal); 720 | DumpAllSymbols(pGlobal); 721 | DumpAllGlobals(pGlobal); 722 | DumpAllTypes(pGlobal); 723 | DumpAllFiles(pSession, pGlobal); 724 | DumpAllLines(pSession, pGlobal); 725 | DumpAllSecContribs(pSession); 726 | DumpAllDebugStreams(pSession); 727 | DumpAllInjectedSources(pSession); 728 | DumpAllFPO(pSession); 729 | DumpAllOEMs(pGlobal); 730 | } 731 | 732 | //////////////////////////////////////////////////////////// 733 | // Dump all the modules information 734 | // 735 | bool DumpAllMods(IDiaSymbol *pGlobal) 736 | { 737 | wprintf(L"\n\n*** MODULES\n\n"); 738 | 739 | // Retrieve all the compiland symbols 740 | 741 | IDiaEnumSymbols *pEnumSymbols; 742 | 743 | if (FAILED(pGlobal->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols))) { 744 | return false; 745 | } 746 | 747 | IDiaSymbol *pCompiland; 748 | ULONG celt = 0; 749 | ULONG iMod = 1; 750 | 751 | while (SUCCEEDED(pEnumSymbols->Next(1, &pCompiland, &celt)) && (celt == 1)) { 752 | BSTR bstrName; 753 | 754 | if (pCompiland->get_name(&bstrName) != S_OK) { 755 | wprintf(L"ERROR - Failed to get the compiland's name\n"); 756 | 757 | pCompiland->Release(); 758 | pEnumSymbols->Release(); 759 | 760 | return false; 761 | } 762 | 763 | wprintf(L"%04X %s\n", iMod++, bstrName); 764 | 765 | // Deallocate the string allocated previously by the call to get_name 766 | 767 | SysFreeString(bstrName); 768 | 769 | pCompiland->Release(); 770 | } 771 | 772 | pEnumSymbols->Release(); 773 | 774 | putwchar(L'\n'); 775 | 776 | return true; 777 | } 778 | 779 | //////////////////////////////////////////////////////////// 780 | // Dump all the public symbols - SymTagPublicSymbol 781 | // 782 | bool DumpAllPublics(IDiaSymbol *pGlobal) 783 | { 784 | wprintf(L"\n\n*** PUBLICS\n\n"); 785 | 786 | // Retrieve all the public symbols 787 | 788 | IDiaEnumSymbols *pEnumSymbols; 789 | 790 | if (FAILED(pGlobal->findChildren(SymTagPublicSymbol, NULL, nsNone, &pEnumSymbols))) { 791 | return false; 792 | } 793 | 794 | IDiaSymbol *pSymbol; 795 | ULONG celt = 0; 796 | 797 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 798 | PrintPublicSymbol(pSymbol); 799 | 800 | pSymbol->Release(); 801 | } 802 | 803 | pEnumSymbols->Release(); 804 | 805 | putwchar(L'\n'); 806 | 807 | return true; 808 | } 809 | 810 | //////////////////////////////////////////////////////////// 811 | // Dump all the symbol information stored in the compilands 812 | // 813 | bool DumpAllSymbols(IDiaSymbol *pGlobal) 814 | { 815 | wprintf(L"\n\n*** SYMBOLS\n\n\n"); 816 | 817 | // Retrieve the compilands first 818 | 819 | IDiaEnumSymbols *pEnumSymbols; 820 | 821 | if (FAILED(pGlobal->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols))) { 822 | return false; 823 | } 824 | 825 | IDiaSymbol *pCompiland; 826 | ULONG celt = 0; 827 | 828 | while (SUCCEEDED(pEnumSymbols->Next(1, &pCompiland, &celt)) && (celt == 1)) { 829 | wprintf(L"\n** Module: "); 830 | 831 | // Retrieve the name of the module 832 | 833 | BSTR bstrName; 834 | 835 | if (pCompiland->get_name(&bstrName) != S_OK) { 836 | wprintf(L"(???)\n\n"); 837 | } 838 | 839 | else { 840 | wprintf(L"%s\n\n", bstrName); 841 | 842 | SysFreeString(bstrName); 843 | } 844 | 845 | // Find all the symbols defined in this compiland and print their info 846 | 847 | IDiaEnumSymbols *pEnumChildren; 848 | 849 | if (SUCCEEDED(pCompiland->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) { 850 | IDiaSymbol *pSymbol; 851 | ULONG celtChildren = 0; 852 | 853 | while (SUCCEEDED(pEnumChildren->Next(1, &pSymbol, &celtChildren)) && (celtChildren == 1)) { 854 | PrintSymbol(pSymbol, 0); 855 | pSymbol->Release(); 856 | } 857 | 858 | pEnumChildren->Release(); 859 | } 860 | 861 | pCompiland->Release(); 862 | } 863 | 864 | pEnumSymbols->Release(); 865 | 866 | putwchar(L'\n'); 867 | 868 | return true; 869 | } 870 | 871 | //////////////////////////////////////////////////////////// 872 | // Dump all the global symbols - SymTagFunction, 873 | // SymTagThunk and SymTagData 874 | // 875 | bool DumpAllGlobals(IDiaSymbol *pGlobal) 876 | { 877 | IDiaEnumSymbols *pEnumSymbols; 878 | IDiaSymbol *pSymbol; 879 | enum SymTagEnum dwSymTags[] = { SymTagFunction, SymTagThunk, SymTagData }; 880 | ULONG celt = 0; 881 | 882 | wprintf(L"\n\n*** GLOBALS\n\n"); 883 | 884 | for (size_t i = 0; i < _countof(dwSymTags); i++, pEnumSymbols = NULL) { 885 | if (SUCCEEDED(pGlobal->findChildren(dwSymTags[i], NULL, nsNone, &pEnumSymbols))) { 886 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 887 | PrintGlobalSymbol(pSymbol); 888 | 889 | pSymbol->Release(); 890 | } 891 | 892 | pEnumSymbols->Release(); 893 | } 894 | 895 | else { 896 | wprintf(L"ERROR - DumpAllGlobals() returned no symbols\n"); 897 | 898 | return false; 899 | } 900 | } 901 | 902 | putwchar(L'\n'); 903 | 904 | return true; 905 | } 906 | 907 | //////////////////////////////////////////////////////////// 908 | // Dump all the types information 909 | // (type symbols can be UDTs, enums or typedefs) 910 | // 911 | bool DumpAllTypes(IDiaSymbol *pGlobal) 912 | { 913 | wprintf(L"\n\n*** TYPES\n"); 914 | 915 | bool f1 = DumpAllUDTs(pGlobal); 916 | bool f2 = DumpAllEnums(pGlobal); 917 | bool f3 = DumpAllTypedefs(pGlobal); 918 | 919 | return f1 && f2 && f3; 920 | } 921 | 922 | //////////////////////////////////////////////////////////// 923 | // Dump all the user defined types (UDT) 924 | // 925 | bool DumpAllUDTs(IDiaSymbol *pGlobal) 926 | { 927 | wprintf(L"\n\n** User Defined Types\n\n"); 928 | 929 | IDiaEnumSymbols *pEnumSymbols; 930 | 931 | if (FAILED(pGlobal->findChildren(SymTagUDT, NULL, nsNone, &pEnumSymbols))) { 932 | wprintf(L"ERROR - DumpAllUDTs() returned no symbols\n"); 933 | 934 | return false; 935 | } 936 | 937 | IDiaSymbol *pSymbol; 938 | ULONG celt = 0; 939 | 940 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 941 | PrintTypeInDetail(pSymbol, 0); 942 | 943 | pSymbol->Release(); 944 | } 945 | 946 | pEnumSymbols->Release(); 947 | 948 | putwchar(L'\n'); 949 | 950 | return true; 951 | } 952 | 953 | //////////////////////////////////////////////////////////// 954 | // Dump all the enum types from the pdb 955 | // 956 | bool DumpAllEnums(IDiaSymbol *pGlobal) 957 | { 958 | wprintf(L"\n\n** ENUMS\n\n"); 959 | 960 | IDiaEnumSymbols *pEnumSymbols; 961 | 962 | if (FAILED(pGlobal->findChildren(SymTagEnum, NULL, nsNone, &pEnumSymbols))) { 963 | wprintf(L"ERROR - DumpAllEnums() returned no symbols\n"); 964 | 965 | return false; 966 | } 967 | 968 | IDiaSymbol *pSymbol; 969 | ULONG celt = 0; 970 | 971 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 972 | PrintTypeInDetail(pSymbol, 0); 973 | 974 | pSymbol->Release(); 975 | } 976 | 977 | pEnumSymbols->Release(); 978 | 979 | putwchar(L'\n'); 980 | 981 | return true; 982 | } 983 | 984 | //////////////////////////////////////////////////////////// 985 | // Dump all the typedef types from the pdb 986 | // 987 | bool DumpAllTypedefs(IDiaSymbol *pGlobal) 988 | { 989 | wprintf(L"\n\n** TYPEDEFS\n\n"); 990 | 991 | IDiaEnumSymbols *pEnumSymbols; 992 | 993 | if (FAILED(pGlobal->findChildren(SymTagTypedef, NULL, nsNone, &pEnumSymbols))) { 994 | wprintf(L"ERROR - DumpAllTypedefs() returned no symbols\n"); 995 | 996 | return false; 997 | } 998 | 999 | IDiaSymbol *pSymbol; 1000 | ULONG celt = 0; 1001 | 1002 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 1003 | PrintTypeInDetail(pSymbol, 0); 1004 | 1005 | pSymbol->Release(); 1006 | } 1007 | 1008 | pEnumSymbols->Release(); 1009 | 1010 | putwchar(L'\n'); 1011 | 1012 | return true; 1013 | } 1014 | 1015 | //////////////////////////////////////////////////////////// 1016 | // Dump OEM specific types 1017 | // 1018 | bool DumpAllOEMs(IDiaSymbol *pGlobal) 1019 | { 1020 | wprintf(L"\n\n*** OEM Specific types\n\n"); 1021 | 1022 | IDiaEnumSymbols *pEnumSymbols; 1023 | 1024 | if (FAILED(pGlobal->findChildren(SymTagCustomType, NULL, nsNone, &pEnumSymbols))) { 1025 | wprintf(L"ERROR - DumpAllOEMs() returned no symbols\n"); 1026 | 1027 | return false; 1028 | } 1029 | 1030 | IDiaSymbol *pSymbol; 1031 | ULONG celt = 0; 1032 | 1033 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 1034 | PrintTypeInDetail(pSymbol, 0); 1035 | 1036 | pSymbol->Release(); 1037 | } 1038 | 1039 | pEnumSymbols->Release(); 1040 | 1041 | putwchar(L'\n'); 1042 | 1043 | return true; 1044 | } 1045 | 1046 | //////////////////////////////////////////////////////////// 1047 | // For each compiland in the PDB dump all the source files 1048 | // 1049 | bool DumpAllFiles(IDiaSession *pSession, IDiaSymbol *pGlobal) 1050 | { 1051 | wprintf(L"\n\n*** FILES\n\n"); 1052 | 1053 | // In order to find the source files, we have to look at the image's compilands/modules 1054 | 1055 | IDiaEnumSymbols *pEnumSymbols; 1056 | 1057 | if (FAILED(pGlobal->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols))) { 1058 | return false; 1059 | } 1060 | 1061 | IDiaSymbol *pCompiland; 1062 | ULONG celt = 0; 1063 | 1064 | while (SUCCEEDED(pEnumSymbols->Next(1, &pCompiland, &celt)) && (celt == 1)) { 1065 | BSTR bstrName; 1066 | 1067 | if (pCompiland->get_name(&bstrName) == S_OK) { 1068 | wprintf(L"\nCompiland = %s\n\n", bstrName); 1069 | 1070 | SysFreeString(bstrName); 1071 | } 1072 | 1073 | // Every compiland could contain multiple references to the source files which were used to build it 1074 | // Retrieve all source files by compiland by passing NULL for the name of the source file 1075 | 1076 | IDiaEnumSourceFiles *pEnumSourceFiles; 1077 | 1078 | if (SUCCEEDED(pSession->findFile(pCompiland, NULL, nsNone, &pEnumSourceFiles))) { 1079 | IDiaSourceFile *pSourceFile; 1080 | 1081 | while (SUCCEEDED(pEnumSourceFiles->Next(1, &pSourceFile, &celt)) && (celt == 1)) { 1082 | PrintSourceFile(pSourceFile); 1083 | putwchar(L'\n'); 1084 | 1085 | pSourceFile->Release(); 1086 | } 1087 | 1088 | pEnumSourceFiles->Release(); 1089 | } 1090 | 1091 | putwchar(L'\n'); 1092 | 1093 | pCompiland->Release(); 1094 | } 1095 | 1096 | pEnumSymbols->Release(); 1097 | 1098 | return true; 1099 | } 1100 | 1101 | //////////////////////////////////////////////////////////// 1102 | // Dump all the line numbering information contained in the PDB 1103 | // Only function symbols have corresponding line numbering information 1104 | bool DumpAllLines(IDiaSession *pSession, IDiaSymbol *pGlobal) 1105 | { 1106 | wprintf(L"\n\n*** LINES\n\n"); 1107 | 1108 | // First retrieve the compilands/modules 1109 | 1110 | IDiaEnumSymbols *pEnumSymbols; 1111 | 1112 | if (FAILED(pGlobal->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols))) { 1113 | return false; 1114 | } 1115 | 1116 | IDiaSymbol *pCompiland; 1117 | ULONG celt = 0; 1118 | 1119 | while (SUCCEEDED(pEnumSymbols->Next(1, &pCompiland, &celt)) && (celt == 1)) { 1120 | IDiaEnumSymbols *pEnumFunction; 1121 | 1122 | // For every function symbol defined in the compiland, retrieve and print the line numbering info 1123 | 1124 | if (SUCCEEDED(pCompiland->findChildren(SymTagFunction, NULL, nsNone, &pEnumFunction))) { 1125 | IDiaSymbol *pFunction; 1126 | 1127 | while (SUCCEEDED(pEnumFunction->Next(1, &pFunction, &celt)) && (celt == 1)) { 1128 | PrintLines(pSession, pFunction); 1129 | 1130 | pFunction->Release(); 1131 | } 1132 | 1133 | pEnumFunction->Release(); 1134 | } 1135 | 1136 | pCompiland->Release(); 1137 | } 1138 | 1139 | pEnumSymbols->Release(); 1140 | 1141 | putwchar(L'\n'); 1142 | 1143 | return true; 1144 | } 1145 | 1146 | //////////////////////////////////////////////////////////// 1147 | // Dump all the line numbering information for a given RVA 1148 | // and a given range 1149 | // 1150 | bool DumpAllLines(IDiaSession *pSession, DWORD dwRVA, DWORD dwRange) 1151 | { 1152 | // Retrieve and print the lines that corresponds to a specified RVA 1153 | 1154 | IDiaEnumLineNumbers *pLines; 1155 | 1156 | if (FAILED(pSession->findLinesByRVA(dwRVA, dwRange, &pLines))) { 1157 | return false; 1158 | } 1159 | 1160 | PrintLines(pLines); 1161 | 1162 | pLines->Release(); 1163 | 1164 | putwchar(L'\n'); 1165 | 1166 | return true; 1167 | } 1168 | 1169 | //////////////////////////////////////////////////////////// 1170 | // Dump all the section contributions from the PDB 1171 | // 1172 | // Section contributions are stored in a table which will 1173 | // be retrieved via IDiaSession->getEnumTables through 1174 | // QueryInterface()using the REFIID of the IDiaEnumSectionContribs 1175 | // 1176 | bool DumpAllSecContribs(IDiaSession *pSession) 1177 | { 1178 | wprintf(L"\n\n*** SECTION CONTRIBUTION\n\n"); 1179 | 1180 | IDiaEnumSectionContribs *pEnumSecContribs; 1181 | 1182 | if (FAILED(GetTable(pSession, __uuidof(IDiaEnumSectionContribs), (void **) &pEnumSecContribs))) { 1183 | return false; 1184 | } 1185 | 1186 | wprintf(L" RVA Address Size Module\n"); 1187 | 1188 | IDiaSectionContrib *pSecContrib; 1189 | ULONG celt = 0; 1190 | 1191 | while (SUCCEEDED(pEnumSecContribs->Next(1, &pSecContrib, &celt)) && (celt == 1)) { 1192 | PrintSecContribs(pSecContrib); 1193 | 1194 | pSecContrib->Release(); 1195 | } 1196 | 1197 | pEnumSecContribs->Release(); 1198 | 1199 | putwchar(L'\n'); 1200 | 1201 | return true; 1202 | } 1203 | 1204 | //////////////////////////////////////////////////////////// 1205 | // Dump all debug data streams contained in the PDB 1206 | // 1207 | bool DumpAllDebugStreams(IDiaSession *pSession) 1208 | { 1209 | IDiaEnumDebugStreams *pEnumStreams; 1210 | 1211 | wprintf(L"\n\n*** DEBUG STREAMS\n\n"); 1212 | 1213 | // Retrieve an enumerated sequence of debug data streams 1214 | 1215 | if (FAILED(pSession->getEnumDebugStreams(&pEnumStreams))) { 1216 | return false; 1217 | } 1218 | 1219 | IDiaEnumDebugStreamData *pStream; 1220 | ULONG celt = 0; 1221 | 1222 | for (; SUCCEEDED(pEnumStreams->Next(1, &pStream, &celt)) && (celt == 1); pStream = NULL) { 1223 | PrintStreamData(pStream); 1224 | 1225 | pStream->Release(); 1226 | } 1227 | 1228 | pEnumStreams->Release(); 1229 | 1230 | putwchar(L'\n'); 1231 | 1232 | return true; 1233 | } 1234 | 1235 | //////////////////////////////////////////////////////////// 1236 | // Dump all the injected source from the PDB 1237 | // 1238 | // Injected sources data is stored in a table which will 1239 | // be retrieved via IDiaSession->getEnumTables through 1240 | // QueryInterface()using the REFIID of the IDiaEnumSectionContribs 1241 | // 1242 | bool DumpAllInjectedSources(IDiaSession *pSession) 1243 | { 1244 | wprintf(L"\n\n*** INJECTED SOURCES TABLE\n\n"); 1245 | 1246 | IDiaEnumInjectedSources *pEnumInjSources = NULL; 1247 | 1248 | if (SUCCEEDED(GetTable(pSession, __uuidof(IDiaEnumInjectedSources), (void **) &pEnumInjSources))) { 1249 | return false; 1250 | } 1251 | 1252 | IDiaInjectedSource *pInjSource; 1253 | ULONG celt = 0; 1254 | 1255 | while (SUCCEEDED(pEnumInjSources->Next(1, &pInjSource, &celt)) && (celt == 1)) { 1256 | PrintGeneric(pInjSource); 1257 | 1258 | pInjSource->Release(); 1259 | } 1260 | 1261 | pEnumInjSources->Release(); 1262 | 1263 | putwchar(L'\n'); 1264 | 1265 | return true; 1266 | } 1267 | 1268 | //////////////////////////////////////////////////////////// 1269 | // Dump info corresponing to a given injected source filename 1270 | // 1271 | bool DumpInjectedSource(IDiaSession *pSession, const wchar_t *szName) 1272 | { 1273 | // Retrieve a source that has been placed into the symbol store by attribute providers or 1274 | // other components of the compilation process 1275 | 1276 | IDiaEnumInjectedSources *pEnumInjSources; 1277 | 1278 | if (FAILED(pSession->findInjectedSource(szName, &pEnumInjSources))) { 1279 | wprintf(L"ERROR - DumpInjectedSources() could not find %s\n", szName); 1280 | 1281 | return false; 1282 | } 1283 | 1284 | IDiaInjectedSource *pInjSource; 1285 | ULONG celt = 0; 1286 | 1287 | while (SUCCEEDED(pEnumInjSources->Next(1, &pInjSource, &celt)) && (celt == 1)) { 1288 | PrintGeneric(pInjSource); 1289 | 1290 | pInjSource->Release(); 1291 | } 1292 | 1293 | pEnumInjSources->Release(); 1294 | 1295 | return true; 1296 | } 1297 | 1298 | //////////////////////////////////////////////////////////// 1299 | // Dump all the source file information stored in the PDB 1300 | // We have to go through every compiland in order to retrieve 1301 | // all the information otherwise checksums for instance 1302 | // will not be available 1303 | // Compilands can have multiple source files with the same 1304 | // name but different content which produces diffrent 1305 | // checksums 1306 | // 1307 | bool DumpAllSourceFiles(IDiaSession *pSession, IDiaSymbol *pGlobal) 1308 | { 1309 | wprintf(L"\n\n*** SOURCE FILES\n\n"); 1310 | 1311 | // To get the complete source file info we must go through the compiland first 1312 | // by passing NULL instead all the source file names only will be retrieved 1313 | 1314 | IDiaEnumSymbols *pEnumSymbols; 1315 | 1316 | if (FAILED(pGlobal->findChildren(SymTagCompiland, NULL, nsNone, &pEnumSymbols))) { 1317 | return false; 1318 | } 1319 | 1320 | IDiaSymbol *pCompiland; 1321 | ULONG celt = 0; 1322 | 1323 | while (SUCCEEDED(pEnumSymbols->Next(1, &pCompiland, &celt)) && (celt == 1)) { 1324 | BSTR bstrName; 1325 | 1326 | if (pCompiland->get_name(&bstrName) == S_OK) { 1327 | wprintf(L"\nCompiland = %s\n\n", bstrName); 1328 | 1329 | SysFreeString(bstrName); 1330 | } 1331 | 1332 | // Every compiland could contain multiple references to the source files which were used to build it 1333 | // Retrieve all source files by compiland by passing NULL for the name of the source file 1334 | 1335 | IDiaEnumSourceFiles *pEnumSourceFiles; 1336 | 1337 | if (SUCCEEDED(pSession->findFile(pCompiland, NULL, nsNone, &pEnumSourceFiles))) { 1338 | IDiaSourceFile *pSourceFile; 1339 | 1340 | while (SUCCEEDED(pEnumSourceFiles->Next(1, &pSourceFile, &celt)) && (celt == 1)) { 1341 | PrintSourceFile(pSourceFile); 1342 | putwchar(L'\n'); 1343 | 1344 | pSourceFile->Release(); 1345 | } 1346 | 1347 | pEnumSourceFiles->Release(); 1348 | } 1349 | 1350 | putwchar(L'\n'); 1351 | 1352 | pCompiland->Release(); 1353 | } 1354 | 1355 | pEnumSymbols->Release(); 1356 | 1357 | return true; 1358 | } 1359 | 1360 | //////////////////////////////////////////////////////////// 1361 | // Dump all the FPO info 1362 | // 1363 | // FPO data stored in a table which will be retrieved via 1364 | // IDiaSession->getEnumTables through QueryInterface() 1365 | // using the REFIID of the IDiaEnumFrameData 1366 | // 1367 | bool DumpAllFPO(IDiaSession *pSession) 1368 | { 1369 | IDiaEnumFrameData *pEnumFrameData; 1370 | 1371 | wprintf(L"\n\n*** FPO\n\n"); 1372 | 1373 | if (FAILED(GetTable(pSession, __uuidof(IDiaEnumFrameData), (void **) &pEnumFrameData))) { 1374 | return false; 1375 | } 1376 | 1377 | IDiaFrameData *pFrameData; 1378 | ULONG celt = 0; 1379 | 1380 | while (SUCCEEDED(pEnumFrameData->Next(1, &pFrameData, &celt)) && (celt == 1)) { 1381 | PrintFrameData(pFrameData); 1382 | 1383 | pFrameData->Release(); 1384 | } 1385 | 1386 | pEnumFrameData->Release(); 1387 | 1388 | putwchar(L'\n'); 1389 | 1390 | return true; 1391 | } 1392 | 1393 | //////////////////////////////////////////////////////////// 1394 | // Dump FPO info for a function at the specified RVA 1395 | // 1396 | bool DumpFPO(IDiaSession *pSession, DWORD dwRVA) 1397 | { 1398 | IDiaEnumFrameData *pEnumFrameData; 1399 | 1400 | // Retrieve first the table holding all the FPO info 1401 | 1402 | if ((dwRVA != 0) && SUCCEEDED(GetTable(pSession, __uuidof(IDiaEnumFrameData), (void **) &pEnumFrameData))) { 1403 | IDiaFrameData *pFrameData; 1404 | 1405 | // Retrieve the frame data corresponding to the given RVA 1406 | 1407 | if (SUCCEEDED(pEnumFrameData->frameByRVA(dwRVA, &pFrameData))) { 1408 | PrintGeneric(pFrameData); 1409 | 1410 | pFrameData->Release(); 1411 | } 1412 | 1413 | else { 1414 | // Some function might not have FPO data available (see ASM funcs like strcpy) 1415 | 1416 | wprintf(L"ERROR - DumpFPO() frameByRVA invalid RVA: 0x%08X\n", dwRVA); 1417 | 1418 | pEnumFrameData->Release(); 1419 | 1420 | return false; 1421 | } 1422 | 1423 | pEnumFrameData->Release(); 1424 | } 1425 | 1426 | else { 1427 | wprintf(L"ERROR - DumpFPO() GetTable\n"); 1428 | 1429 | return false; 1430 | } 1431 | 1432 | putwchar(L'\n'); 1433 | 1434 | return true; 1435 | } 1436 | 1437 | //////////////////////////////////////////////////////////// 1438 | // Dump FPO info for a specified function symbol using its 1439 | // name (a regular expression string is used for the search) 1440 | // 1441 | bool DumpFPO(IDiaSession *pSession, IDiaSymbol *pGlobal, const wchar_t *szSymbolName) 1442 | { 1443 | IDiaEnumSymbols *pEnumSymbols; 1444 | IDiaSymbol *pSymbol; 1445 | ULONG celt = 0; 1446 | DWORD dwRVA; 1447 | 1448 | // Find first all the function symbols that their names matches the search criteria 1449 | 1450 | if (FAILED(pGlobal->findChildren(SymTagFunction, szSymbolName, nsRegularExpression, &pEnumSymbols))) { 1451 | wprintf(L"ERROR - DumpFPO() findChildren could not find symol %s\n", szSymbolName); 1452 | 1453 | return false; 1454 | } 1455 | 1456 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 1457 | if (pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) { 1458 | PrintPublicSymbol(pSymbol); 1459 | 1460 | DumpFPO(pSession, dwRVA); 1461 | } 1462 | 1463 | pSymbol->Release(); 1464 | } 1465 | 1466 | pEnumSymbols->Release(); 1467 | 1468 | putwchar(L'\n'); 1469 | 1470 | return true; 1471 | } 1472 | 1473 | //////////////////////////////////////////////////////////// 1474 | // Dump a specified compiland and all the symbols defined in it 1475 | // 1476 | bool DumpCompiland(IDiaSymbol *pGlobal, const wchar_t *szCompName) 1477 | { 1478 | IDiaEnumSymbols *pEnumSymbols; 1479 | 1480 | if (FAILED(pGlobal->findChildren(SymTagCompiland, szCompName, nsCaseInsensitive, &pEnumSymbols))) { 1481 | return false; 1482 | } 1483 | 1484 | IDiaSymbol *pCompiland; 1485 | ULONG celt = 0; 1486 | 1487 | while (SUCCEEDED(pEnumSymbols->Next(1, &pCompiland, &celt)) && (celt == 1)) { 1488 | wprintf(L"\n** Module: "); 1489 | 1490 | // Retrieve the name of the module 1491 | 1492 | BSTR bstrName; 1493 | 1494 | if (pCompiland->get_name(&bstrName) != S_OK) { 1495 | wprintf(L"(???)\n\n"); 1496 | } 1497 | 1498 | else { 1499 | wprintf(L"%s\n\n", bstrName); 1500 | 1501 | SysFreeString(bstrName); 1502 | } 1503 | 1504 | IDiaEnumSymbols *pEnumChildren; 1505 | 1506 | if (SUCCEEDED(pCompiland->findChildren(SymTagNull, NULL, nsNone, &pEnumChildren))) { 1507 | IDiaSymbol *pSymbol; 1508 | ULONG celt_ = 0; 1509 | 1510 | while (SUCCEEDED(pEnumChildren->Next(1, &pSymbol, &celt_)) && (celt_ == 1)) { 1511 | PrintSymbol(pSymbol, 0); 1512 | 1513 | pSymbol->Release(); 1514 | } 1515 | 1516 | pEnumChildren->Release(); 1517 | } 1518 | 1519 | pCompiland->Release(); 1520 | } 1521 | 1522 | pEnumSymbols->Release(); 1523 | 1524 | return true; 1525 | } 1526 | 1527 | //////////////////////////////////////////////////////////// 1528 | // Dump the line numbering information for a specified RVA 1529 | // 1530 | bool DumpLines(IDiaSession *pSession, DWORD dwRVA) 1531 | { 1532 | IDiaEnumLineNumbers *pLines; 1533 | 1534 | if (FAILED(pSession->findLinesByRVA(dwRVA, MAX_RVA_LINES_BYTES_RANGE, &pLines))) { 1535 | return false; 1536 | } 1537 | 1538 | PrintLines(pLines); 1539 | 1540 | pLines->Release(); 1541 | 1542 | return true; 1543 | } 1544 | 1545 | //////////////////////////////////////////////////////////// 1546 | // Dump the all line numbering information for a specified 1547 | // function symbol name (as a regular expression string) 1548 | // 1549 | bool DumpLines(IDiaSession *pSession, IDiaSymbol *pGlobal, const wchar_t *szFuncName) 1550 | { 1551 | IDiaEnumSymbols *pEnumSymbols; 1552 | 1553 | if (FAILED(pGlobal->findChildren(SymTagFunction, szFuncName, nsRegularExpression, &pEnumSymbols))) { 1554 | return false; 1555 | } 1556 | 1557 | IDiaSymbol *pFunction; 1558 | ULONG celt = 0; 1559 | 1560 | while (SUCCEEDED(pEnumSymbols->Next(1, &pFunction, &celt)) && (celt == 1)) { 1561 | PrintLines(pSession, pFunction); 1562 | 1563 | pFunction->Release(); 1564 | } 1565 | 1566 | pEnumSymbols->Release(); 1567 | 1568 | return true; 1569 | } 1570 | 1571 | //////////////////////////////////////////////////////////// 1572 | // Dump the symbol information corresponding to a specified RVA 1573 | // 1574 | bool DumpSymbolWithRVA(IDiaSession *pSession, DWORD dwRVA, const wchar_t *szChildname) 1575 | { 1576 | IDiaSymbol *pSymbol; 1577 | LONG lDisplacement; 1578 | 1579 | if (FAILED(pSession->findSymbolByRVAEx(dwRVA, SymTagNull, &pSymbol, &lDisplacement))) { 1580 | return false; 1581 | } 1582 | 1583 | wprintf(L"Displacement = 0x%X\n", lDisplacement); 1584 | 1585 | PrintGeneric(pSymbol); 1586 | 1587 | DumpSymbolWithChildren(pSymbol, szChildname); 1588 | 1589 | while (pSymbol != NULL) { 1590 | IDiaSymbol *pParent; 1591 | 1592 | if ((pSymbol->get_lexicalParent(&pParent) == S_OK) && pParent) { 1593 | wprintf(L"\nParent\n"); 1594 | 1595 | PrintSymbol(pParent, 0); 1596 | 1597 | pSymbol->Release(); 1598 | 1599 | pSymbol = pParent; 1600 | } 1601 | 1602 | else { 1603 | pSymbol->Release(); 1604 | break; 1605 | } 1606 | } 1607 | 1608 | return true; 1609 | } 1610 | 1611 | //////////////////////////////////////////////////////////// 1612 | // Dump the symbols information where their names matches a 1613 | // specified regular expression string 1614 | // 1615 | bool DumpSymbolsWithRegEx(IDiaSymbol *pGlobal, const wchar_t *szRegEx, const wchar_t *szChildname) 1616 | { 1617 | IDiaEnumSymbols *pEnumSymbols; 1618 | 1619 | if (FAILED(pGlobal->findChildren(SymTagNull, szRegEx, nsRegularExpression, &pEnumSymbols))) { 1620 | return false; 1621 | } 1622 | 1623 | bool bReturn = true; 1624 | 1625 | IDiaSymbol *pSymbol; 1626 | ULONG celt = 0; 1627 | 1628 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 1629 | PrintGeneric(pSymbol); 1630 | 1631 | bReturn = DumpSymbolWithChildren(pSymbol, szChildname); 1632 | 1633 | pSymbol->Release(); 1634 | } 1635 | 1636 | pEnumSymbols->Release(); 1637 | 1638 | return bReturn; 1639 | } 1640 | 1641 | //////////////////////////////////////////////////////////// 1642 | // Dump the information corresponding to a symbol name which 1643 | // is a children of the specified parent symbol 1644 | // 1645 | bool DumpSymbolWithChildren(IDiaSymbol *pSymbol, const wchar_t *szChildname) 1646 | { 1647 | if (szChildname != NULL) { 1648 | IDiaEnumSymbols *pEnumSyms; 1649 | 1650 | if (FAILED(pSymbol->findChildren(SymTagNull, szChildname, nsRegularExpression, &pEnumSyms))) { 1651 | return false; 1652 | } 1653 | 1654 | IDiaSymbol *pChild; 1655 | DWORD celt = 1; 1656 | 1657 | while (SUCCEEDED(pEnumSyms->Next(celt, &pChild, &celt)) && (celt == 1)) { 1658 | PrintGeneric(pChild); 1659 | PrintSymbol(pChild, 0); 1660 | 1661 | pChild->Release(); 1662 | } 1663 | 1664 | pEnumSyms->Release(); 1665 | } 1666 | 1667 | else { 1668 | // If the specified name is NULL then only the parent symbol data is displayed 1669 | 1670 | DWORD dwSymTag; 1671 | 1672 | if ((pSymbol->get_symTag(&dwSymTag) == S_OK) && (dwSymTag == SymTagPublicSymbol)) { 1673 | PrintPublicSymbol(pSymbol); 1674 | } 1675 | 1676 | else { 1677 | PrintSymbol(pSymbol, 0); 1678 | } 1679 | } 1680 | 1681 | return true; 1682 | } 1683 | 1684 | //////////////////////////////////////////////////////////// 1685 | // Dump all the type symbols information that matches their 1686 | // names to a specified regular expression string 1687 | // 1688 | bool DumpType(IDiaSymbol *pGlobal, const wchar_t *szRegEx) 1689 | { 1690 | IDiaEnumSymbols *pEnumSymbols; 1691 | 1692 | if (FAILED(pGlobal->findChildren(SymTagUDT, szRegEx, nsRegularExpression, &pEnumSymbols))) { 1693 | return false; 1694 | } 1695 | 1696 | IDiaSymbol *pSymbol; 1697 | ULONG celt = 0; 1698 | 1699 | while (SUCCEEDED(pEnumSymbols->Next(1, &pSymbol, &celt)) && (celt == 1)) { 1700 | PrintTypeInDetail(pSymbol, 0); 1701 | 1702 | pSymbol->Release(); 1703 | } 1704 | 1705 | pEnumSymbols->Release(); 1706 | 1707 | return true; 1708 | } 1709 | 1710 | //////////////////////////////////////////////////////////// 1711 | // Dump line numbering information for a given file name and 1712 | // an optional line number 1713 | // 1714 | bool DumpLinesForSourceFile(IDiaSession *pSession, const wchar_t *szFileName, DWORD dwLine) 1715 | { 1716 | IDiaEnumSourceFiles *pEnumSrcFiles; 1717 | 1718 | if (FAILED(pSession->findFile(NULL, szFileName, nsFNameExt, &pEnumSrcFiles))) { 1719 | return false; 1720 | } 1721 | 1722 | IDiaSourceFile *pSrcFile; 1723 | ULONG celt = 0; 1724 | 1725 | while (SUCCEEDED(pEnumSrcFiles->Next(1, &pSrcFile, &celt)) && (celt == 1)) { 1726 | IDiaEnumSymbols *pEnumCompilands; 1727 | 1728 | if (pSrcFile->get_compilands(&pEnumCompilands) == S_OK) { 1729 | IDiaSymbol *pCompiland; 1730 | 1731 | celt = 0; 1732 | while (SUCCEEDED(pEnumCompilands->Next(1, &pCompiland, &celt)) && (celt == 1)) { 1733 | BSTR bstrName; 1734 | 1735 | if (pCompiland->get_name(&bstrName) == S_OK) { 1736 | wprintf(L"Compiland = %s\n", bstrName); 1737 | 1738 | SysFreeString(bstrName); 1739 | } 1740 | 1741 | else { 1742 | wprintf(L"Compiland = (???)\n"); 1743 | } 1744 | 1745 | IDiaEnumLineNumbers *pLines; 1746 | 1747 | if (dwLine != 0) { 1748 | if (SUCCEEDED(pSession->findLinesByLinenum(pCompiland, pSrcFile, dwLine, 0, &pLines))) { 1749 | PrintLines(pLines); 1750 | 1751 | pLines->Release(); 1752 | } 1753 | } 1754 | 1755 | else { 1756 | if (SUCCEEDED(pSession->findLines(pCompiland, pSrcFile, &pLines))) { 1757 | PrintLines(pLines); 1758 | 1759 | pLines->Release(); 1760 | } 1761 | } 1762 | 1763 | pCompiland->Release(); 1764 | } 1765 | 1766 | pEnumCompilands->Release(); 1767 | } 1768 | 1769 | pSrcFile->Release(); 1770 | } 1771 | 1772 | pEnumSrcFiles->Release(); 1773 | 1774 | return true; 1775 | } 1776 | 1777 | //////////////////////////////////////////////////////////// 1778 | // Dump public symbol information for a given number of 1779 | // symbols around a given RVA address 1780 | // 1781 | bool DumpPublicSymbolsSorted(IDiaSession *pSession, DWORD dwRVA, DWORD dwRange, bool bReverse) 1782 | { 1783 | IDiaEnumSymbolsByAddr *pEnumSymsByAddr; 1784 | 1785 | if (FAILED(pSession->getSymbolsByAddr(&pEnumSymsByAddr))) { 1786 | return false; 1787 | } 1788 | 1789 | IDiaSymbol *pSymbol; 1790 | 1791 | if (SUCCEEDED(pEnumSymsByAddr->symbolByRVA(dwRVA, &pSymbol))) { 1792 | if (dwRange == 0) { 1793 | PrintPublicSymbol(pSymbol); 1794 | } 1795 | 1796 | ULONG celt; 1797 | ULONG i; 1798 | 1799 | if (bReverse) { 1800 | pSymbol->Release(); 1801 | 1802 | i = 0; 1803 | 1804 | for (pSymbol = NULL; (i < dwRange) && SUCCEEDED(pEnumSymsByAddr->Next(1, &pSymbol, &celt)) && (celt == 1); i++) { 1805 | PrintPublicSymbol(pSymbol); 1806 | 1807 | pSymbol->Release(); 1808 | } 1809 | } 1810 | 1811 | else { 1812 | PrintPublicSymbol(pSymbol); 1813 | 1814 | pSymbol->Release(); 1815 | 1816 | i = 1; 1817 | 1818 | for (pSymbol = NULL; (i < dwRange) && SUCCEEDED(pEnumSymsByAddr->Prev(1, &pSymbol, &celt)) && (celt == 1); i++) { 1819 | PrintPublicSymbol(pSymbol); 1820 | } 1821 | } 1822 | } 1823 | 1824 | pEnumSymsByAddr->Release(); 1825 | 1826 | return true; 1827 | } 1828 | 1829 | //////////////////////////////////////////////////////////// 1830 | // Dump label symbol information at a given RVA 1831 | // 1832 | bool DumpLabel(IDiaSession *pSession, DWORD dwRVA) 1833 | { 1834 | IDiaSymbol *pSymbol; 1835 | LONG lDisplacement; 1836 | 1837 | if (FAILED(pSession->findSymbolByRVAEx(dwRVA, SymTagLabel, &pSymbol, &lDisplacement)) || (pSymbol == NULL)) { 1838 | return false; 1839 | } 1840 | 1841 | wprintf(L"Displacement = 0x%X\n", lDisplacement); 1842 | 1843 | PrintGeneric(pSymbol); 1844 | 1845 | pSymbol->Release(); 1846 | 1847 | return true; 1848 | } 1849 | 1850 | //////////////////////////////////////////////////////////// 1851 | // Dump annotation symbol information at a given RVA 1852 | // 1853 | bool DumpAnnotations(IDiaSession *pSession, DWORD dwRVA) 1854 | { 1855 | IDiaSymbol *pSymbol; 1856 | LONG lDisplacement; 1857 | 1858 | if (FAILED(pSession->findSymbolByRVAEx(dwRVA, SymTagAnnotation, &pSymbol, &lDisplacement)) || (pSymbol == NULL)) { 1859 | return false; 1860 | } 1861 | 1862 | wprintf(L"Displacement = 0x%X\n", lDisplacement); 1863 | 1864 | PrintGeneric(pSymbol); 1865 | 1866 | pSymbol->Release(); 1867 | 1868 | return true; 1869 | } 1870 | 1871 | struct OMAP_DATA 1872 | { 1873 | DWORD dwRVA; 1874 | DWORD dwRVATo; 1875 | }; 1876 | 1877 | //////////////////////////////////////////////////////////// 1878 | // 1879 | bool DumpMapToSrc(IDiaSession *pSession, DWORD dwRVA) 1880 | { 1881 | IDiaEnumDebugStreams *pEnumStreams; 1882 | IDiaEnumDebugStreamData *pStream; 1883 | ULONG celt; 1884 | 1885 | if (FAILED(pSession->getEnumDebugStreams(&pEnumStreams))) { 1886 | return false; 1887 | } 1888 | 1889 | celt = 0; 1890 | 1891 | for (; SUCCEEDED(pEnumStreams->Next(1, &pStream, &celt)) && (celt == 1); pStream = NULL) { 1892 | BSTR bstrName; 1893 | 1894 | if (pStream->get_name(&bstrName) != S_OK) { 1895 | bstrName = NULL; 1896 | } 1897 | 1898 | if (bstrName && wcscmp(bstrName, L"OMAPTO") == 0) { 1899 | OMAP_DATA data, datasav; 1900 | DWORD cbData; 1901 | DWORD dwRVATo = 0; 1902 | unsigned int i; 1903 | 1904 | datasav.dwRVATo = 0; 1905 | datasav.dwRVA = 0; 1906 | 1907 | while (SUCCEEDED(pStream->Next(1, sizeof(data), &cbData, (BYTE*) &data, &celt)) && (celt == 1)) { 1908 | if (dwRVA > data.dwRVA) { 1909 | datasav = data; 1910 | continue; 1911 | } 1912 | 1913 | else if (dwRVA == data.dwRVA) { 1914 | dwRVATo = data.dwRVATo; 1915 | } 1916 | 1917 | else if (datasav.dwRVATo) { 1918 | dwRVATo = datasav.dwRVATo + (dwRVA - datasav.dwRVA); 1919 | } 1920 | break; 1921 | } 1922 | 1923 | wprintf(L"image rva = %08X ==> source rva = %08X\n\nRelated OMAP entries:\n", dwRVA, dwRVATo); 1924 | wprintf(L"image rva ==> source rva\n"); 1925 | wprintf(L"%08X ==> %08X\n", datasav.dwRVA, datasav.dwRVATo); 1926 | 1927 | i = 0; 1928 | 1929 | do { 1930 | wprintf(L"%08X ==> %08X\n", data.dwRVA, data.dwRVATo); 1931 | } 1932 | while ((++i) < 5 && SUCCEEDED(pStream->Next(1, sizeof(data), &cbData, (BYTE*) &data, &celt)) && (celt == 1)); 1933 | } 1934 | 1935 | if (bstrName != NULL) { 1936 | SysFreeString(bstrName); 1937 | } 1938 | 1939 | pStream->Release(); 1940 | } 1941 | 1942 | pEnumStreams->Release(); 1943 | 1944 | return true; 1945 | } 1946 | 1947 | //////////////////////////////////////////////////////////// 1948 | // 1949 | bool DumpMapFromSrc(IDiaSession *pSession, DWORD dwRVA) 1950 | { 1951 | IDiaEnumDebugStreams *pEnumStreams; 1952 | 1953 | if (FAILED(pSession->getEnumDebugStreams(&pEnumStreams))) { 1954 | return false; 1955 | } 1956 | 1957 | IDiaEnumDebugStreamData *pStream; 1958 | ULONG celt = 0; 1959 | 1960 | for (; SUCCEEDED(pEnumStreams->Next(1, &pStream, &celt)) && (celt == 1); pStream = NULL) { 1961 | BSTR bstrName; 1962 | 1963 | if (pStream->get_name(&bstrName) != S_OK) { 1964 | bstrName = NULL; 1965 | } 1966 | 1967 | if (bstrName && wcscmp(bstrName, L"OMAPFROM") == 0) { 1968 | OMAP_DATA data; 1969 | OMAP_DATA datasav; 1970 | DWORD cbData; 1971 | DWORD dwRVATo = 0; 1972 | unsigned int i; 1973 | 1974 | datasav.dwRVATo = 0; 1975 | datasav.dwRVA = 0; 1976 | 1977 | while (SUCCEEDED(pStream->Next(1, sizeof(data), &cbData, (BYTE*) &data, &celt)) && (celt == 1)) { 1978 | if (dwRVA > data.dwRVA) { 1979 | datasav = data; 1980 | continue; 1981 | } 1982 | 1983 | else if (dwRVA == data.dwRVA) { 1984 | dwRVATo = data.dwRVATo; 1985 | } 1986 | 1987 | else if (datasav.dwRVATo) { 1988 | dwRVATo = datasav.dwRVATo + (dwRVA - datasav.dwRVA); 1989 | } 1990 | break; 1991 | } 1992 | 1993 | wprintf(L"source rva = %08X ==> image rva = %08X\n\nRelated OMAP entries:\n", dwRVA, dwRVATo); 1994 | wprintf(L"source rva ==> image rva\n"); 1995 | wprintf(L"%08X ==> %08X\n", datasav.dwRVA, datasav.dwRVATo); 1996 | 1997 | i = 0; 1998 | 1999 | do { 2000 | wprintf(L"%08X ==> %08X\n", data.dwRVA, data.dwRVATo); 2001 | } 2002 | while ((++i) < 5 && SUCCEEDED(pStream->Next(1, sizeof(data), &cbData, (BYTE*) &data, &celt)) && (celt == 1)); 2003 | } 2004 | 2005 | if (bstrName != NULL) { 2006 | SysFreeString(bstrName); 2007 | } 2008 | 2009 | pStream->Release(); 2010 | } 2011 | 2012 | pEnumStreams->Release(); 2013 | 2014 | return true; 2015 | } 2016 | 2017 | //////////////////////////////////////////////////////////// 2018 | // Retreive the table that matches the given iid 2019 | // 2020 | // A PDB table could store the section contributions, the frame data, 2021 | // the injected sources 2022 | // 2023 | HRESULT GetTable(IDiaSession *pSession, REFIID iid, void **ppUnk) 2024 | { 2025 | IDiaEnumTables *pEnumTables; 2026 | 2027 | if (FAILED(pSession->getEnumTables(&pEnumTables))) { 2028 | wprintf(L"ERROR - GetTable() getEnumTables\n"); 2029 | 2030 | return E_FAIL; 2031 | } 2032 | 2033 | IDiaTable *pTable; 2034 | ULONG celt = 0; 2035 | 2036 | while (SUCCEEDED(pEnumTables->Next(1, &pTable, &celt)) && (celt == 1)) { 2037 | // There's only one table that matches the given IID 2038 | 2039 | if (SUCCEEDED(pTable->QueryInterface(iid, (void **) ppUnk))) { 2040 | pTable->Release(); 2041 | pEnumTables->Release(); 2042 | 2043 | return S_OK; 2044 | } 2045 | 2046 | pTable->Release(); 2047 | } 2048 | 2049 | pEnumTables->Release(); 2050 | 2051 | return E_FAIL; 2052 | } 2053 | -------------------------------------------------------------------------------- /dia2dump.h: -------------------------------------------------------------------------------- 1 | #include "dia2.h" 2 | 3 | extern const wchar_t *g_szFilename; 4 | extern IDiaDataSource *g_pDiaDataSource; 5 | extern IDiaSession *g_pDiaSession; 6 | extern IDiaSymbol *g_pGlobalSymbol; 7 | extern DWORD g_dwMachineType; 8 | 9 | void PrintHelpOptions(); 10 | bool ParseArg(int , wchar_t *[]); 11 | 12 | void Cleanup(); 13 | bool LoadDataFromPdb(const wchar_t *, IDiaDataSource **, IDiaSession **, IDiaSymbol **); 14 | 15 | void DumpAllPdbInfo(IDiaSession *, IDiaSymbol *); 16 | bool DumpAllMods(IDiaSymbol *); 17 | bool DumpAllPublics(IDiaSymbol *); 18 | bool DumpCompiland(IDiaSymbol *, const wchar_t *); 19 | bool DumpAllSymbols(IDiaSymbol *); 20 | bool DumpAllGlobals(IDiaSymbol *); 21 | bool DumpAllTypes(IDiaSymbol *); 22 | bool DumpAllUDTs(IDiaSymbol *); 23 | bool DumpAllEnums(IDiaSymbol *); 24 | bool DumpAllTypedefs(IDiaSymbol *); 25 | bool DumpAllOEMs(IDiaSymbol *); 26 | bool DumpAllFiles(IDiaSession *, IDiaSymbol *); 27 | bool DumpAllLines(IDiaSession *, IDiaSymbol *); 28 | bool DumpAllLines(IDiaSession *, DWORD, DWORD); 29 | bool DumpAllSecContribs(IDiaSession *); 30 | bool DumpAllDebugStreams(IDiaSession *); 31 | bool DumpAllInjectedSources(IDiaSession *); 32 | bool DumpInjectedSource(IDiaSession *, const wchar_t *); 33 | bool DumpAllSourceFiles(IDiaSession *, IDiaSymbol *); 34 | bool DumpAllFPO(IDiaSession *); 35 | bool DumpFPO(IDiaSession *, DWORD); 36 | bool DumpFPO(IDiaSession *, IDiaSymbol *, const wchar_t *); 37 | bool DumpSymbolWithRVA(IDiaSession *, DWORD, const wchar_t *); 38 | bool DumpSymbolsWithRegEx(IDiaSymbol *, const wchar_t *, const wchar_t *); 39 | bool DumpSymbolWithChildren(IDiaSymbol *, const wchar_t *); 40 | bool DumpLines(IDiaSession *, DWORD); 41 | bool DumpLines(IDiaSession *, IDiaSymbol *, const wchar_t *); 42 | bool DumpType(IDiaSymbol *, const wchar_t *); 43 | bool DumpLinesForSourceFile(IDiaSession *, const wchar_t *, DWORD); 44 | bool DumpPublicSymbolsSorted(IDiaSession *, DWORD, DWORD, bool); 45 | bool DumpLabel(IDiaSession *, DWORD); 46 | bool DumpAnnotations(IDiaSession *, DWORD); 47 | bool DumpMapToSrc(IDiaSession *, DWORD); 48 | bool DumpMapFromSrc(IDiaSession *, DWORD); 49 | 50 | HRESULT GetTable(IDiaSession *, REFIID, void **); 51 | 52 | /////////////////////////////////////////////////////////////////// 53 | // Functions defined in regs.cpp 54 | const wchar_t *SzNameC7Reg(USHORT, DWORD); 55 | const wchar_t *SzNameC7Reg(USHORT); 56 | -------------------------------------------------------------------------------- /regs.h: -------------------------------------------------------------------------------- 1 | extern const wchar_t * const rgRegX86[]; 2 | extern const wchar_t * const rgRegAMD64[]; 3 | extern const wchar_t * const rgRegMips[]; 4 | extern const wchar_t * const rgReg68k[]; 5 | extern const wchar_t * const rgRegAlpha[]; 6 | extern const wchar_t * const rgRegPpc[]; 7 | extern const wchar_t * const rgRegSh[]; 8 | extern const wchar_t * const rgRegArm[]; 9 | 10 | typedef struct MapIa64Reg{ 11 | CV_HREG_e iCvReg; 12 | const wchar_t* wszRegName; 13 | }MapIa64Reg; 14 | extern const MapIa64Reg mpIa64regSz[]; 15 | int cmpIa64regSz( const void* , const void* ); 16 | 17 | extern DWORD g_dwMachineType; 18 | const wchar_t* SzNameC7Reg( USHORT , DWORD ); 19 | const wchar_t* SzNameC7Reg( USHORT ); 20 | -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // Dia2Dump.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | 9 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | #include "dia2.h" 18 | 19 | -------------------------------------------------------------------------------- /x_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static const wchar_t* rgCallConv[] = 4 | { 5 | L"", // CV_CALL_NEAR_C (__cdecl) 6 | L"__fastcall", // CV_CALL_NEAR_FAST 7 | L"__stdcall" // CV_CALL_NEAR_STD 8 | L"__syscall", // CV_CALL_NEAR_SYS 9 | L"__thoscall", // CV_CALL_THISCALL 10 | L"__clrcall" // CV_CALL_CLRCALL 11 | }; 12 | 13 | class Bstr 14 | { 15 | public: 16 | BSTR _str; 17 | 18 | inline Bstr() : _str(NULL) {} 19 | inline Bstr(BSTR str) : _str(str) {} 20 | 21 | inline BSTR* operator &() { Release(); return &_str; } 22 | inline BSTR operator *() { return _str; } 23 | 24 | inline void Release() { if (_str) { SysFreeString(_str); _str = NULL; } } 25 | inline ~Bstr() { Release(); } 26 | }; 27 | 28 | template 29 | class ComRef 30 | { 31 | public: 32 | T* _ptr; 33 | 34 | inline ComRef() : _ptr(NULL) {} 35 | inline ComRef(T* ptr) : _ptr(ptr) {} 36 | inline ComRef(const ComRef& other) { _ptr = other._ptr; if (_ptr) { _ptr->AddRef(); } } 37 | inline ComRef& operator=(const ComRef& other) { Release(); _ptr = other._ptr; if (_ptr) { _ptr->AddRef(); } return *this; } 38 | 39 | inline T** operator &() { Release(); return &_ptr; } 40 | inline T* operator *() { return _ptr; } 41 | inline T* operator ->() { return _ptr; } 42 | 43 | inline void Release() { if (_ptr) { _ptr->Release(); _ptr = NULL; } } 44 | inline ~ComRef() { Release(); } 45 | }; 46 | 47 | class SymbolEnumerator 48 | { 49 | public: 50 | ComRef _enumerator; 51 | ComRef _sym; 52 | 53 | inline SymbolEnumerator() {} 54 | 55 | inline bool Find(IDiaSymbol* parent, enum SymTagEnum tagType, const wchar_t* filter = NULL, NameSearchOptions opt = nsNone) { 56 | return (SUCCEEDED(parent->findChildren(tagType, filter, opt, &_enumerator))); 57 | } 58 | 59 | inline bool Next() { 60 | ULONG celt = 0; 61 | return (SUCCEEDED(_enumerator->Next(1, &_sym, &celt)) && (celt == 1)); 62 | } 63 | 64 | inline IDiaSymbol* operator *() { return _sym._ptr; } 65 | inline IDiaSymbol* operator ->() { return _sym._ptr; } 66 | inline ComRef& ref() { return _sym; } 67 | }; 68 | 69 | static ComRef FindSymbol(IDiaSymbol* parent, enum SymTagEnum tagType, const wchar_t* filter = NULL) 70 | { 71 | ComRef enumerator; 72 | if (SUCCEEDED(parent->findChildren(tagType, filter, nsNone, &enumerator))) { 73 | IDiaSymbol* child = NULL; 74 | ULONG celt = 0; 75 | if (SUCCEEDED(enumerator->Next(1, &child, &celt)) && (celt == 1)) { 76 | return ComRef(child); 77 | } 78 | } 79 | return ComRef(); 80 | } 81 | -------------------------------------------------------------------------------- /x_cpp_enum.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static void CppPrintEnum(IDiaSymbol *pGlobal, const wchar_t* filter, FILE* fd = stdout) 4 | { 5 | SymbolEnumerator symbol; 6 | if (symbol.Find(pGlobal, SymTagEnum, filter)) { 7 | while (symbol.Next()) { 8 | 9 | Bstr name; 10 | symbol->get_name(&name); 11 | if (!IsAllowedName(*name)) return; 12 | 13 | std::wstring nameFixed(fixEnumName(*name)); 14 | fwprintf(fd, L"enum class %s {\n", nameFixed.c_str()); 15 | 16 | SymbolEnumerator data; 17 | if (data.Find(*symbol, SymTagData, NULL)) { 18 | while (data.Next()) { 19 | 20 | DWORD dwDataKind = 0; 21 | data->get_dataKind(&dwDataKind); 22 | 23 | if (dwDataKind == DataIsConstant) 24 | { 25 | Bstr dataName; 26 | data->get_name(&dataName); 27 | 28 | fwprintf(fd, L"\t"); 29 | fwprintf(fd, L"%s =", *dataName); 30 | 31 | VARIANT vt = { VT_EMPTY }; 32 | if (data->get_value(&vt) == S_OK) { 33 | 34 | std::wstring valStr; 35 | PrintVariantX(vt, &valStr); 36 | fwprintf(fd, L"%s", valStr.c_str()); 37 | 38 | VariantClear((VARIANTARG *)&vt); 39 | } 40 | 41 | fwprintf(fd, L",\n"); 42 | } 43 | } 44 | } 45 | 46 | fwprintf(fd, L"};\n"); 47 | } 48 | } 49 | } 50 | 51 | static void CppPrintEnums(IDiaSymbol *global, ResolvedUdtGraphPtr graph, FILE* fd = stdout) 52 | { 53 | std::unordered_set uniqEnums; 54 | 55 | for (auto& node : graph->nodes) { 56 | for (auto& idep : node->dep_s) { 57 | if (*idep.second) { 58 | 59 | DWORD tag; 60 | idep.second->get_symTag(&tag); 61 | 62 | if (tag == SymTagEnum) { 63 | if (uniqEnums.find(idep.first) == uniqEnums.end()) { 64 | 65 | uniqEnums.insert(idep.first); 66 | CppPrintEnum(global, idep.first.c_str(), fd); 67 | fwprintf(fd, L"\n"); 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /x_cpp_gen_file.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static void CppGenEnums(IDiaSymbol *global, ResolvedUdtGraphPtr graph) 4 | { 5 | std::unordered_set uniqEnums; 6 | 7 | for (auto& node : graph->nodes) { 8 | for (auto& idep : node->dep_s) { 9 | if (*idep.second) { 10 | 11 | DWORD tag; 12 | idep.second->get_symTag(&tag); 13 | 14 | if (tag == SymTagEnum) { 15 | 16 | std::wstring nameFixed(fixEnumName(idep.first)); 17 | std::wstring fileName(nameFixed + L".h"); 18 | 19 | if (uniqEnums.find(nameFixed) == uniqEnums.end()) { 20 | uniqEnums.insert(nameFixed); 21 | 22 | FILE* fd = NULL; 23 | _wfopen_s(&fd, fileName.c_str(), L"wt"); 24 | if (fd) 25 | { 26 | fwprintf(fd, L"#pragma once\n\n"); 27 | CppPrintEnum(global, idep.first.c_str(), fd); 28 | fclose(fd); 29 | } 30 | } 31 | } 32 | } 33 | else { 34 | //wprintf(L"%s is null\n", idep.first.c_str()); 35 | } 36 | } 37 | } 38 | } 39 | 40 | static void CppGenClass(IDiaSymbol *pGlobal, IDiaSymbol *pUDT, UdtNodePtr& node, ResolvedUdtGraphPtr& resolved, UdtGraphPtr& graph) 41 | { 42 | DWORD symTag; 43 | if (pUDT->get_symTag(&symTag) != S_OK) return; 44 | if (symTag != SymTagUDT) return; 45 | 46 | DWORD kind = 0; 47 | pUDT->get_udtKind(&kind); 48 | if (!(kind == UdtStruct || kind == UdtClass)) 49 | { 50 | return; 51 | } 52 | 53 | Bstr name; 54 | if (pUDT->get_name(&name) != S_OK) { 55 | return; 56 | } 57 | 58 | std::wstring uname(*name); 59 | std::wstring nameFixed(fixName(uname)); 60 | std::wstring namePrefix; 61 | std::wstring nameInner; 62 | { 63 | size_t pos = uname.find_last_of(L"::"); 64 | if (pos != std::string::npos) 65 | { 66 | namePrefix.assign(uname.substr(0, pos - 1)); 67 | nameInner.assign(uname.substr(pos + 1)); 68 | } 69 | else 70 | { 71 | namePrefix.clear(); 72 | nameInner.assign(uname); 73 | } 74 | } 75 | 76 | std::wstring fileName(nameFixed + L".h"); 77 | FILE* fd = NULL; 78 | _wfopen_s(&fd, fileName.c_str(), L"wt"); 79 | if (!fd) return; 80 | 81 | struct ScopedFile { 82 | FILE* _fd; 83 | ScopedFile(FILE* fd) : _fd(fd) {} 84 | ScopedFile() { if (_fd) { fclose(_fd); } } 85 | }; 86 | ScopedFile sfd(fd); 87 | 88 | fwprintf(fd, L"#pragma once\n\n"); 89 | 90 | // deps 91 | { 92 | std::unordered_set uniq; 93 | int count = 0; 94 | 95 | for (auto& idep : node->dep_s) { 96 | 97 | if (!endsWith(idep.first, L'*') && IsAllowedName(idep.first.c_str()) && !startsWith(idep.first, L"void")) { 98 | 99 | std::wstring name(idep.first); 100 | trim(name); 101 | 102 | auto inode = graph->nodes.find(name); 103 | if (inode != graph->nodes.end()) { 104 | 105 | auto className(fixName(name)); 106 | 107 | if (IsTemplateClass(idep.first.c_str())) 108 | { 109 | size_t inner = className.find_first_of(L'<'); 110 | auto templName(className.substr(0, inner)); 111 | 112 | if (!templName.empty() && uniq.find(templName) == uniq.end()) { 113 | uniq.insert(templName); 114 | 115 | fwprintf(fd, L"#include \"%s.h\"\n", templName.c_str()); 116 | ++count; 117 | } 118 | } 119 | else 120 | { 121 | if (!className.empty() && uniq.find(className) == uniq.end()) { 122 | uniq.insert(className); 123 | 124 | fwprintf(fd, L"#include \"%s.h\"\n", className.c_str()); 125 | ++count; 126 | } 127 | } 128 | } 129 | else { 130 | auto depSym = FindSymbol(pGlobal, SymTagEnum, name.c_str()); 131 | if (*depSym) 132 | { 133 | DWORD depTag = 0; 134 | depSym->get_symTag(&depTag); 135 | if (depTag == SymTagEnum) 136 | { 137 | auto enumName(fixEnumName(name)); 138 | 139 | if (!enumName.empty() && uniq.find(enumName) == uniq.end()) { 140 | uniq.insert(enumName); 141 | fwprintf(fd, L"#include \"%s.h\"\n", enumName.c_str()); 142 | ++count; 143 | } 144 | } 145 | } 146 | } 147 | } 148 | } 149 | if (count) { 150 | fwprintf(fd, L"\n"); 151 | } 152 | } 153 | 154 | // forward decls 155 | { 156 | std::unordered_set uniq; 157 | int count = 0; 158 | for (auto& idep : node->dep_s) { 159 | 160 | if (endsWith(idep.first, L'*') && IsAllowedName(idep.first.c_str()) && !startsWith(idep.first, L"void")) { 161 | 162 | std::wstring name(idep.first); 163 | replace(name, L"*", L""); 164 | trim(name); 165 | 166 | auto inode = graph->nodes.find(name); 167 | if (inode != graph->nodes.end()) { 168 | 169 | auto fixedName(fixName(name)); 170 | if (!fixedName.empty() && uniq.find(fixedName) == uniq.end()) { 171 | uniq.insert(fixedName); 172 | 173 | DWORD kind; 174 | inode->second->symbol->get_udtKind(&kind); 175 | fwprintf(fd, L"%s %s;\n", rgUdtKind[kind], fixedName.c_str()); 176 | ++count; 177 | } 178 | } 179 | } 180 | } 181 | if (count) { 182 | fwprintf(fd, L"\n"); 183 | } 184 | } 185 | 186 | // enums 187 | { 188 | #if 0 189 | for (auto& idep : node->dep_s) { 190 | if (*idep.second) { 191 | 192 | DWORD tag; 193 | idep.second->get_symTag(&tag) 194 | 195 | if (tag == SymTagEnum) { 196 | if (uniqEnums.find(idep.first) == uniqEnums.end()) { 197 | 198 | uniqEnums.insert(idep.first); 199 | CppPrintEnum(pGlobal, idep.first.c_str(), fd); 200 | } 201 | } 202 | } 203 | } 204 | #endif 205 | } 206 | 207 | // class 208 | fwprintf(fd, L"%s %s", rgUdtKind[kind], nameFixed.c_str()); 209 | 210 | // base class 211 | { 212 | int baseId = 0; 213 | SymbolEnumerator symbol; 214 | if (symbol.Find(pUDT, SymTagBaseClass, NULL)) { 215 | while (symbol.Next()) { 216 | 217 | if (!baseId) fwprintf(fd, L" : "); 218 | else fwprintf(fd, L", "); 219 | fwprintf(fd, L"public "); 220 | 221 | Bstr baseName; 222 | symbol->get_name(&baseName); 223 | 224 | std::wstring baseNameFixed(fixName(*baseName)); 225 | fwprintf(fd, L"%s", baseNameFixed.c_str()); 226 | baseId++; 227 | } 228 | } 229 | } 230 | 231 | // body 232 | fwprintf(fd, L" {\n"); 233 | fwprintf(fd, L"public:\n"); 234 | 235 | // data 236 | { 237 | SymbolEnumerator symbol; 238 | if (symbol.Find(pUDT, SymTagData, NULL)) { 239 | while (symbol.Next()) { 240 | 241 | DWORD dwDataKind; 242 | symbol->get_dataKind(&dwDataKind); 243 | 244 | if (dwDataKind == DataIsMember) 245 | { 246 | Bstr fieldName; 247 | symbol->get_name(&fieldName); 248 | 249 | ComRef fieldType; 250 | symbol->get_type(&fieldType); 251 | 252 | DWORD fieldTypeTag; 253 | fieldType->get_symTag(&fieldTypeTag); 254 | 255 | fwprintf(fd, L"\t"); 256 | 257 | if (fieldTypeTag == SymTagPointerType) 258 | { 259 | } 260 | 261 | std::wstring fieldTypeStr; 262 | PrintTypeX(*fieldType, &fieldTypeStr); 263 | fwprintf(fd, L"%s", fieldTypeStr.c_str()); 264 | 265 | fwprintf(fd, L" %s", *fieldName); 266 | 267 | if (fieldTypeTag == SymTagArrayType) 268 | { 269 | std::wstring arrTypeStr; 270 | PrintArraySizeX(*fieldType, &arrTypeStr); 271 | fwprintf(fd, L"%s", arrTypeStr.c_str()); 272 | } 273 | 274 | fwprintf(fd, L";\n"); 275 | } 276 | } 277 | } 278 | } 279 | 280 | // stubs 281 | { 282 | int funcLineId = 0; 283 | SymbolEnumerator symbol; 284 | if (symbol.Find(pUDT, SymTagFunction, NULL)) { 285 | while (symbol.Next()) { 286 | 287 | DWORD funcId; 288 | symbol->get_symIndexId(&funcId); 289 | 290 | Bstr funcName; 291 | symbol->get_name(&funcName); 292 | if (wcsstr(*funcName, L"__vecDelDtor")) continue; 293 | if (wcsstr(*funcName, L"__local_vftable_ctor_closure")) continue; 294 | 295 | BOOL isPure = FALSE; 296 | symbol->get_pure(&isPure); 297 | 298 | BOOL isVirtual = FALSE; 299 | symbol->get_virtual(&isVirtual); 300 | 301 | if (isPure && !isVirtual) continue; 302 | 303 | ULONGLONG len = 0; 304 | DWORD dwLocType = 0, dwRVA = 0, dwSect = 0, dwOff = 0; 305 | symbol->get_length(&len); 306 | symbol->get_locationType(&dwLocType); 307 | symbol->get_relativeVirtualAddress(&dwRVA); 308 | symbol->get_addressSection(&dwSect); 309 | symbol->get_addressOffset(&dwOff); 310 | 311 | BOOL isOptimized = (dwLocType == 0); 312 | //if (isOptimized && !isVirtual) continue; 313 | 314 | DWORD vtpo = 0; // virtual table pointer offset 315 | DWORD vfid = 0; // virtual function id in VT 316 | if (isVirtual) { 317 | GetVirtualFuncInfo(pUDT, *symbol, vtpo, vfid); 318 | } 319 | 320 | DWORD callConv = 0; 321 | symbol->get_callingConvention(&callConv); 322 | 323 | ComRef funcType; 324 | symbol->get_type(&funcType); 325 | 326 | ComRef returnType; 327 | funcType->get_type(&returnType); 328 | 329 | BOOL isDtor = (wcsstr(*funcName, L"~") ? TRUE : FALSE); 330 | BOOL isCtor = (wcscmp(*funcName, nameInner.c_str()) == 0); 331 | BOOL isFunc = !(isCtor || isDtor); 332 | 333 | // skip non virtual dtors 334 | if (!isVirtual && isDtor) continue; 335 | 336 | if (!funcLineId++) { 337 | fwprintf(fd, L"\n"); 338 | } 339 | 340 | if (!isVirtual) { 341 | 342 | fwprintf(fd, L"\t"); 343 | if (isDtor) { 344 | //fwprintf(fd, L"~%s", nameFixed.c_str()); 345 | } 346 | else if (isCtor) { 347 | fwprintf(fd, L"%s", nameFixed.c_str()); 348 | } 349 | else { 350 | std::wstring returnTypeStr; 351 | PrintTypeX(*returnType, &returnTypeStr); 352 | fwprintf(fd, L"%s", returnTypeStr.c_str()); 353 | 354 | fwprintf(fd, L" "); 355 | 356 | if (callConv > 0) { 357 | fwprintf(fd, L"%s ", rgCallConv[callConv]); // not __cdecl 358 | } 359 | 360 | if (isVirtual) { 361 | fwprintf(fd, L"%s_impl", *funcName); 362 | } 363 | else { 364 | fwprintf(fd, L"%s", *funcName); 365 | } 366 | } 367 | fwprintf(fd, L"("); 368 | std::wstring funcArgsStr; 369 | PrintFunctionArgsX(*symbol, TRUE, TRUE, NULL, &funcArgsStr); 370 | fwprintf(fd, L"%s", funcArgsStr.c_str()); 371 | fwprintf(fd, L")"); 372 | 373 | fwprintf(fd, L" {} "); 374 | fwprintf(fd, L"\n"); 375 | } 376 | 377 | if (isVirtual) { 378 | if (isDtor) { 379 | fwprintf(fd, L"\tvirtual ~%s()", nameFixed.c_str()); 380 | } 381 | else { 382 | fwprintf(fd, L"\tvirtual "); 383 | 384 | std::wstring returnTypeStr; 385 | PrintTypeX(*returnType, &returnTypeStr); 386 | fwprintf(fd, L"%s", returnTypeStr.c_str()); 387 | 388 | fwprintf(fd, L" "); 389 | if (callConv > 0) { 390 | fwprintf(fd, L"%s ", rgCallConv[callConv]); 391 | } 392 | fwprintf(fd, L"%s(", *funcName); 393 | 394 | std::wstring funcArgsStr; 395 | PrintFunctionArgsX(*symbol, TRUE, TRUE, NULL, &funcArgsStr); 396 | fwprintf(fd, L"%s", funcArgsStr.c_str()); 397 | 398 | fwprintf(fd, L")"); 399 | } 400 | if (isPure) { 401 | fwprintf(fd, L" = 0;"); 402 | } 403 | else { 404 | fwprintf(fd, L" {}"); 405 | } 406 | fwprintf(fd, L" // vf%u", (unsigned int)vfid); 407 | fwprintf(fd, L"\n"); 408 | } 409 | } 410 | } 411 | } 412 | 413 | fwprintf(fd, L"};\n"); // end UDT 414 | fwprintf(fd, L"\n"); 415 | } 416 | -------------------------------------------------------------------------------- /x_cpp_proxy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static void CppProxyPrintForwardDecl(IDiaSymbol *global, ResolvedUdtGraphPtr resolved, UdtGraphPtr graph) 4 | { 5 | std::unordered_set uniq; 6 | 7 | int count = 0; 8 | for (auto& node : resolved->nodes) { 9 | for (auto& idep : node->dep_s) { 10 | 11 | if (endsWith(idep.first, L'*') && IsAllowedName(idep.first.c_str()) && !startsWith(idep.first, L"void")) { 12 | 13 | std::wstring name(idep.first); 14 | replace(name, L"*", L""); 15 | trim(name); 16 | 17 | auto inode = graph->nodes.find(name); 18 | if (inode != graph->nodes.end()) { 19 | 20 | auto fixedName(fixName(name)); 21 | if (!fixedName.empty() && uniq.find(fixedName) == uniq.end()) { 22 | uniq.insert(fixedName); 23 | 24 | DWORD kind; 25 | inode->second->symbol->get_udtKind(&kind); 26 | 27 | wprintf(L"%s %s;\n", rgUdtKind[kind], fixedName.c_str()); 28 | ++count; 29 | } 30 | } 31 | } 32 | } 33 | } 34 | if (count) { 35 | wprintf(L"\n"); 36 | } 37 | } 38 | 39 | static void CppProxyPrintUDT(IDiaSymbol *pUDT, BOOL bGuardObject = FALSE, BOOL bZeroInitialize = FALSE) 40 | { 41 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/lexical-hierarchy-of-symbol-types.md 42 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/class-hierarchy-of-symbol-types.md 43 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/udt.md 44 | 45 | DWORD symTag; 46 | if (pUDT->get_symTag(&symTag) != S_OK) return; 47 | if (symTag != SymTagUDT) return; 48 | 49 | DWORD kind = 0; 50 | pUDT->get_udtKind(&kind); 51 | if (!(kind == UdtStruct || kind == UdtClass)) 52 | { 53 | return; 54 | } 55 | 56 | Bstr name; 57 | if (pUDT->get_name(&name) != S_OK) { 58 | return; 59 | } 60 | 61 | // class 62 | std::wstring uname(*name); 63 | std::wstring nameFixed(fixName(uname)); 64 | std::wstring namePrefix; 65 | std::wstring nameInner; 66 | { 67 | size_t pos = uname.find_last_of(L"::"); 68 | if (pos != std::string::npos) 69 | { 70 | namePrefix.assign(uname.substr(0, pos - 1)); 71 | nameInner.assign(uname.substr(pos + 1)); 72 | } 73 | else 74 | { 75 | namePrefix.clear(); 76 | nameInner.assign(uname); 77 | } 78 | } 79 | 80 | wprintf(L"%s %s", rgUdtKind[kind], nameFixed.c_str()); 81 | 82 | // base class 83 | { 84 | int baseId = 0; 85 | SymbolEnumerator symbol; 86 | if (symbol.Find(pUDT, SymTagBaseClass, NULL)) { 87 | while (symbol.Next()) { 88 | 89 | if (!baseId) wprintf(L" : "); 90 | else wprintf(L", "); 91 | wprintf(L"public "); 92 | 93 | Bstr baseName; 94 | symbol->get_name(&baseName); 95 | 96 | std::wstring baseNameFixed(fixName(*baseName)); 97 | wprintf(L"%s", baseNameFixed.c_str()); 98 | baseId++; 99 | } 100 | } 101 | } 102 | 103 | // body 104 | wprintf(L" {\n"); 105 | wprintf(L"public:\n"); 106 | 107 | BOOL addFakeVtp = FALSE; 108 | 109 | // virtual table ptr 110 | { 111 | BOOL hasIntroVf = FALSE; 112 | BOOL hasOverVf = FALSE; 113 | 114 | SymbolEnumerator symbol; 115 | if (symbol.Find(pUDT, SymTagFunction, NULL)) { 116 | while (symbol.Next()) { 117 | 118 | Bstr funcName; 119 | symbol->get_name(&funcName); 120 | 121 | BOOL isVirtual = FALSE; 122 | symbol->get_virtual(&isVirtual); 123 | 124 | if (isVirtual) { 125 | BOOL isIntro = FALSE; 126 | symbol->get_intro(&isIntro); 127 | 128 | if (isIntro) 129 | hasIntroVf = TRUE; 130 | else 131 | hasOverVf = TRUE; 132 | } 133 | } 134 | } 135 | 136 | if (hasIntroVf && !hasOverVf) 137 | { 138 | addFakeVtp = TRUE; 139 | wprintf(L"\tvoid* _vtable;\n"); 140 | } 141 | } 142 | 143 | // data 144 | { 145 | SymbolEnumerator symbol; 146 | if (symbol.Find(pUDT, SymTagData, NULL)) { 147 | while (symbol.Next()) { 148 | 149 | DWORD dwDataKind; 150 | symbol->get_dataKind(&dwDataKind); 151 | 152 | if (dwDataKind == DataIsMember) 153 | { 154 | Bstr fieldName; 155 | symbol->get_name(&fieldName); 156 | 157 | ComRef fieldType; 158 | symbol->get_type(&fieldType); 159 | 160 | DWORD fieldTypeTag; 161 | fieldType->get_symTag(&fieldTypeTag); 162 | 163 | BOOL isRef = FALSE; 164 | fieldType->get_reference(&isRef); 165 | 166 | wprintf(L"\t"); 167 | if (!isRef) { 168 | PrintTypeX(*fieldType); 169 | } 170 | else { 171 | PrintPointerTypeX(*fieldType, NULL, TRUE); 172 | } 173 | wprintf(L" %s", *fieldName); 174 | 175 | if (fieldTypeTag == SymTagArrayType) 176 | { 177 | PrintArraySizeX(*fieldType); 178 | } 179 | 180 | // default zero initialization 181 | if (bZeroInitialize && (fieldTypeTag == SymTagBaseType || fieldTypeTag == SymTagPointerType || fieldTypeTag == SymTagEnum || fieldTypeTag == SymTagArrayType)) 182 | { 183 | if (!isRef) 184 | { 185 | if (fieldTypeTag == SymTagEnum) 186 | { 187 | // SomeEnum e = {} crashes the compiler LOL 188 | wprintf(L" = ("); 189 | PrintTypeX(*fieldType); 190 | wprintf(L")(0)"); 191 | } 192 | else if (fieldTypeTag == SymTagArrayType) 193 | { 194 | ComRef arrType; 195 | fieldType->get_type(&arrType); 196 | 197 | DWORD arrTypeTag; 198 | arrType->get_symTag(&arrTypeTag); 199 | 200 | if (arrTypeTag == SymTagBaseType || arrTypeTag == SymTagPointerType) 201 | { 202 | wprintf(L" = {}"); 203 | } 204 | } 205 | else 206 | wprintf(L" = 0"); 207 | } 208 | } 209 | 210 | wprintf(L";\n"); 211 | } 212 | } 213 | } 214 | } 215 | 216 | // methods 217 | { 218 | BOOL hasDefConstructor = FALSE; 219 | BOOL hasCtor = FALSE; 220 | BOOL hasDtor = FALSE; 221 | 222 | std::wstring ctorPrefix; 223 | ctorPrefix.assign(L"__cdecl "); 224 | ctorPrefix.assign(nameInner); 225 | ctorPrefix.append(L"::"); 226 | ctorPrefix.append(nameInner); 227 | ctorPrefix.append(L"("); 228 | 229 | std::wstring fixedFuncName; 230 | fixedFuncName.reserve(1024); 231 | 232 | std::wstring funcNamespace(*name); 233 | funcNamespace.append(L"::"); 234 | 235 | SymbolEnumerator symbol; 236 | if (symbol.Find(pUDT, SymTagFunction, NULL)) { 237 | while (symbol.Next()) { 238 | 239 | DWORD funcId; 240 | symbol->get_symIndexId(&funcId); 241 | 242 | Bstr funcName; 243 | symbol->get_name(&funcName); 244 | if (wcsstr(*funcName, L"__vecDelDtor")) continue; 245 | 246 | fixedFuncName.assign(*funcName); 247 | replace(fixedFuncName, funcNamespace, L""); 248 | 249 | Bstr undecName; 250 | symbol->get_undecoratedName(&undecName); 251 | 252 | BOOL isDtor = (wcsstr(*funcName, L"~") ? TRUE : FALSE); 253 | BOOL isCtor = (wcscmp(*funcName, nameInner.c_str()) == 0); 254 | 255 | // HACK for newer msdia 256 | if (wcsstr(*undecName, ctorPrefix.c_str())) 257 | { 258 | isCtor = TRUE; 259 | } 260 | 261 | BOOL isFunc = !(isCtor || isDtor); 262 | 263 | BOOL isPure = FALSE; 264 | symbol->get_pure(&isPure); 265 | 266 | BOOL isVirtual = FALSE; 267 | symbol->get_virtual(&isVirtual); 268 | 269 | BOOL isStatic = FALSE; 270 | symbol->get_isStatic(&isStatic); 271 | 272 | ULONGLONG len = 0; 273 | DWORD dwLocType = 0, dwRVA = 0, dwSect = 0, dwOff = 0; 274 | symbol->get_length(&len); 275 | symbol->get_locationType(&dwLocType); 276 | symbol->get_relativeVirtualAddress(&dwRVA); 277 | symbol->get_addressSection(&dwSect); 278 | symbol->get_addressOffset(&dwOff); 279 | BOOL isOptimized = (dwLocType == 0); 280 | 281 | // HACK for newer msdia 282 | if (isFunc && dwLocType == LocIsStatic && dwRVA && isPure && !isVirtual) 283 | { 284 | isStatic = TRUE; 285 | } 286 | 287 | BOOL isValidVirtual = FALSE; 288 | DWORD vtpo = 0; // virtual table pointer offset 289 | DWORD vfid = 0; // virtual function id in VT 290 | 291 | if (isVirtual) { 292 | isValidVirtual = GetVirtualFuncInfo(pUDT, *symbol, vtpo, vfid); 293 | if (!isValidVirtual) { 294 | wprintf(L"\t#error INVALID VFID %s::%s\n", nameFixed.c_str(), *funcName); 295 | } 296 | } 297 | 298 | DWORD callConv = 0; 299 | symbol->get_callingConvention(&callConv); // rgCallConv[callConv] 300 | 301 | ComRef funcType; 302 | symbol->get_type(&funcType); 303 | 304 | ComRef returnType; 305 | funcType->get_type(&returnType); 306 | 307 | // UDT ctor/dtor 308 | 309 | if (isCtor && !isOptimized) { 310 | hasCtor = TRUE; 311 | wprintf(L"\tinline %s * ctor(", nameFixed.c_str()); 312 | PrintFunctionArgsX(*symbol, TRUE, TRUE); 313 | wprintf(L") {"); 314 | 315 | wprintf(L" typedef "); 316 | wprintf(L"%s *", nameFixed.c_str()); 317 | wprintf(L" (%s::*_fpt)(", nameFixed.c_str()); 318 | PrintFunctionArgsX(*symbol, TRUE, FALSE); 319 | wprintf(L");"); 320 | 321 | wprintf(L" auto _f=xcast<_fpt>(_drva(%u));", (unsigned int)dwRVA); 322 | wprintf(L" return (this->*_f)("); 323 | PrintFunctionArgsX(*symbol, FALSE, TRUE); 324 | wprintf(L");"); 325 | 326 | wprintf(L" }\n"); 327 | } 328 | 329 | if (isDtor && (!isOptimized || (isVirtual && isValidVirtual))) { 330 | hasDtor = TRUE; 331 | wprintf(L"\tinline void dtor() {"); 332 | 333 | wprintf(L" typedef "); 334 | PrintTypeX(*returnType); 335 | wprintf(L" (%s::*_fpt)(", nameFixed.c_str()); 336 | PrintFunctionArgsX(*symbol, TRUE, FALSE); 337 | wprintf(L");"); 338 | 339 | if (isVirtual) { 340 | wprintf(L" auto _f=xcast<_fpt>(get_vfp(this, %u));", (unsigned int)vfid); 341 | } 342 | else { 343 | wprintf(L" auto _f=xcast<_fpt>(_drva(%u));", (unsigned int)dwRVA); 344 | } 345 | wprintf(L" (this->*_f)();"); 346 | 347 | wprintf(L" }\n"); 348 | } 349 | 350 | // direct rva calls 351 | 352 | if (isFunc && !isOptimized) { 353 | 354 | wprintf(L"\tinline "); 355 | if (isStatic) { 356 | wprintf(L"static "); 357 | } 358 | PrintTypeX(*returnType); 359 | wprintf(L" "); 360 | if (callConv > 0) { 361 | wprintf(L"%s ", rgCallConv[callConv]); 362 | } 363 | if (isVirtual) { 364 | wprintf(L"%s_impl", fixedFuncName.c_str()); // funcName 365 | } 366 | else { 367 | wprintf(L"%s", fixedFuncName.c_str()); // funcName 368 | } 369 | wprintf(L"("); 370 | PrintFunctionArgsX(*symbol, TRUE, TRUE); 371 | wprintf(L")"); 372 | 373 | // body 374 | wprintf(L" { "); 375 | 376 | wprintf(L"typedef "); 377 | PrintTypeX(*returnType); 378 | wprintf(L" ("); 379 | if (callConv > 0) { 380 | wprintf(L"%s ", rgCallConv[callConv]); 381 | } 382 | if (!isStatic) { 383 | wprintf(L"%s::", nameFixed.c_str()); 384 | } 385 | wprintf(L"*_fpt)("); 386 | if (isStatic) { 387 | PrintFunctionArgsX(*symbol, TRUE, FALSE); 388 | } 389 | else { 390 | PrintFunctionArgsX(*symbol, TRUE, FALSE); 391 | } 392 | wprintf(L");"); 393 | 394 | if (isStatic) { 395 | wprintf(L" auto _f=(_fpt)_drva(%u);", (unsigned int)dwRVA); 396 | } 397 | else { 398 | wprintf(L" auto _f=xcast<_fpt>(_drva(%u));", (unsigned int)dwRVA); 399 | } 400 | 401 | if (isStatic) { 402 | wprintf(L" return _f("); 403 | } 404 | else { 405 | wprintf(L" return (this->*_f)("); 406 | } 407 | if (isStatic) { 408 | PrintFunctionArgsX(*symbol, FALSE, TRUE); 409 | } 410 | else { 411 | PrintFunctionArgsX(*symbol, FALSE, TRUE); 412 | } 413 | wprintf(L");"); 414 | 415 | wprintf(L" }"); 416 | wprintf(L"\n"); 417 | } 418 | 419 | // virtual redirectors 420 | 421 | #if defined(GEN_VFUNC_REDIR) 422 | if (isVirtual && isFunc) { 423 | wprintf(L"\tinline "); 424 | PrintTypeX(*returnType); 425 | wprintf(L" %s(", fixedFuncName.c_str()); // *funcName 426 | PrintFunctionArgsX(*symbol, TRUE, TRUE); 427 | wprintf(L") {"); 428 | 429 | wprintf(L" typedef "); 430 | PrintTypeX(*returnType); 431 | wprintf(L" (%s::*_fpt)(", nameFixed.c_str()); 432 | PrintFunctionArgsX(*symbol, TRUE, FALSE); 433 | wprintf(L");"); 434 | wprintf(L" auto _f=xcast<_fpt>(get_vfp(this, %u));", (unsigned int)vfid); 435 | wprintf(L" return (this->*_f)("); 436 | PrintFunctionArgsX(*symbol, FALSE, TRUE); 437 | wprintf(L");"); 438 | 439 | wprintf(L" }\n"); 440 | } 441 | #endif 442 | } 443 | } 444 | 445 | if (!hasCtor) { 446 | wprintf(L"\tinline %s * ctor() { return this; }\n", nameFixed.c_str()); 447 | } 448 | 449 | if (!hasDtor) { 450 | wprintf(L"\tinline void dtor() {}\n"); 451 | } 452 | } 453 | 454 | // guard 455 | if (bGuardObject) 456 | { 457 | ULONGLONG len = 0; 458 | pUDT->get_length(&len); 459 | 460 | wprintf(L"\tinline void _guard_obj() {\n"); 461 | wprintf(L"\t\tstatic_assert((sizeof(%s)==%u),\"bad size\");\n", nameFixed.c_str(), (unsigned int)len); 462 | 463 | SymbolEnumerator symbol; 464 | if (symbol.Find(pUDT, SymTagData, NULL)) { 465 | while (symbol.Next()) { 466 | 467 | DWORD dwDataKind; 468 | symbol->get_dataKind(&dwDataKind); 469 | if (dwDataKind == DataIsMember) 470 | { 471 | DWORD locType = 0; 472 | symbol->get_locationType(&locType); 473 | if (locType == LocIsThisRel) 474 | { 475 | LONG off = 0; 476 | if (symbol->get_offset(&off) == S_OK) 477 | { 478 | ComRef fieldType; 479 | symbol->get_type(&fieldType); 480 | BOOL isRef = FALSE; 481 | fieldType->get_reference(&isRef); 482 | 483 | if (!isRef) { 484 | Bstr fieldName; 485 | symbol->get_name(&fieldName); 486 | wprintf(L"\t\tstatic_assert((offsetof(%s,%s)==0x%X),\"bad off\");\n", nameFixed.c_str(), *fieldName, (unsigned int)off); 487 | } 488 | } 489 | } 490 | } 491 | } 492 | } 493 | wprintf(L"\t};\n"); 494 | } 495 | 496 | wprintf(L"};\n"); // end UDT 497 | wprintf(L"\n"); 498 | } 499 | -------------------------------------------------------------------------------- /x_meta.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static std::wstring GetUniqFunctionName(IDiaSymbol *pFunc, BOOL bWithArgs = TRUE) 4 | { 5 | std::wstring result; 6 | 7 | Bstr name; 8 | pFunc->get_name(&name); 9 | result.assign(*name); 10 | 11 | if (bWithArgs) 12 | { 13 | result.append(L"("); 14 | PrintFunctionArgsX(pFunc, TRUE, FALSE, NULL, &result); 15 | result.append(L")"); 16 | } 17 | 18 | return result; 19 | } 20 | 21 | static IDiaSymbol* FindIntroVirtual(IDiaSymbol* pObj, const std::wstring& funcName, DWORD* pBaseOffset, BOOL bWithArgs = TRUE) 22 | { 23 | ComRef enumerator; 24 | ComRef sym; 25 | 26 | if (SUCCEEDED(pObj->findChildren(SymTagFunction, NULL, nsNone, &enumerator))) 27 | { 28 | ULONG celt = 0; 29 | while (SUCCEEDED(enumerator->Next(1, &sym, &celt)) && (celt == 1)) 30 | { 31 | auto name = GetUniqFunctionName(*sym, bWithArgs); 32 | 33 | if ( 34 | (wcscmp(funcName.c_str(), name.c_str()) == 0) 35 | || ((funcName)[0] == L'~' && (name)[0] == L'~')) 36 | { 37 | BOOL isVirtual = FALSE; 38 | sym->get_virtual(&isVirtual); 39 | 40 | BOOL isIntro = FALSE; 41 | sym->get_intro(&isIntro); 42 | 43 | if (isVirtual && isIntro) 44 | { 45 | IDiaSymbol* res = *sym; 46 | sym._ptr = NULL; 47 | return res; 48 | } 49 | } 50 | } 51 | } 52 | 53 | if (SUCCEEDED(pObj->findChildren(SymTagBaseClass, NULL, nsNone, &enumerator))) 54 | { 55 | ULONG celt = 0; 56 | while (SUCCEEDED(enumerator->Next(1, &sym, &celt)) && (celt == 1)) 57 | { 58 | IDiaSymbol* res = FindIntroVirtual(*sym, funcName, pBaseOffset, bWithArgs); 59 | if (res) 60 | { 61 | LONG offset; 62 | if (sym->get_offset(&offset) == S_OK) { 63 | *pBaseOffset += offset; 64 | } 65 | 66 | return res; 67 | } 68 | } 69 | } 70 | 71 | return NULL; 72 | } 73 | 74 | static BOOL GetVirtualFuncInfo(IDiaSymbol* pThis, IDiaSymbol* pFunc, DWORD& vtpo, DWORD& vfid) 75 | { 76 | BOOL res = FALSE; 77 | 78 | vtpo = 0; // virtual table pointer offset 79 | vfid = 0; // virtual function id in VT 80 | 81 | BOOL isVirtual = FALSE; 82 | pFunc->get_virtual(&isVirtual); 83 | 84 | if (isVirtual) 85 | { 86 | DWORD off = 0; 87 | res = (S_OK == pFunc->get_virtualBaseOffset(&off)); 88 | 89 | BOOL isIntro = FALSE; 90 | pFunc->get_intro(&isIntro); 91 | 92 | if (off == 0 && !isIntro) 93 | { 94 | Bstr udtName; 95 | pThis->get_name(&udtName); 96 | 97 | std::wstring udtPrefix(*udtName); 98 | udtPrefix.append(L"::"); 99 | 100 | Bstr symName; 101 | pFunc->get_name(&symName); 102 | 103 | auto funcName = GetUniqFunctionName(pFunc); 104 | 105 | // HACK: on win10 have to remove UDT name prefix 106 | removePrefix(funcName, udtPrefix); 107 | 108 | ComRef intro(FindIntroVirtual(pThis, funcName, &vtpo)); 109 | if (!(*intro)) 110 | { 111 | // HACK: find by function by name without args 112 | funcName = *symName; 113 | removePrefix(funcName, udtPrefix); 114 | intro = FindIntroVirtual(pThis, funcName, &vtpo, FALSE); 115 | } 116 | 117 | if (*intro) 118 | { 119 | res = (S_OK == intro->get_virtualBaseOffset(&off)); 120 | } 121 | else 122 | { 123 | res = FALSE; 124 | } 125 | } 126 | 127 | vfid = off / sizeof(void*); 128 | } 129 | 130 | return res; 131 | } 132 | 133 | static void PrintMetaSym(IDiaSymbol *pSymbol, std::unordered_set& uniq, int depth = 0) 134 | { 135 | // sym 136 | 137 | DWORD symId = 0; 138 | pSymbol->get_symIndexId(&symId); 139 | 140 | if (uniq.find(symId) != uniq.end()) return; 141 | uniq.insert(symId); 142 | 143 | DWORD symTag = 0; 144 | pSymbol->get_symTag(&symTag); 145 | 146 | Bstr symName; 147 | pSymbol->get_name(&symName); 148 | 149 | // type 150 | 151 | DWORD typeId = 0; 152 | DWORD typeTag = 0; 153 | Bstr typeName; 154 | 155 | ComRef type; 156 | if (pSymbol->get_type(&type) == S_OK) 157 | { 158 | type->get_symIndexId(&typeId); 159 | type->get_symTag(&typeTag); 160 | type->get_name(&typeName); 161 | } 162 | 163 | // print 164 | 165 | for (int i = 0; i < depth; ++i) putwchar(L' '); 166 | wprintf(L"//SYM: %u %s \"%s\" # Type: %u %s \"%s\"\n", 167 | (unsigned int)symId, rgTags[symTag], *symName, 168 | (unsigned int)typeId, rgTags[typeTag], *typeName 169 | ); 170 | 171 | if (typeTag == SymTagPointerType) 172 | { 173 | ComRef ptrType; 174 | if (type->get_type(&ptrType) == S_OK) 175 | { 176 | DWORD ptrId = 0; 177 | ptrType->get_symIndexId(&ptrId); 178 | 179 | DWORD ptrTag = 0; 180 | ptrType->get_symTag(&ptrTag); 181 | 182 | Bstr ptrName; 183 | ptrType->get_name(&ptrName); 184 | 185 | for (int i = 0; i < depth; ++i) putwchar(L' '); 186 | wprintf(L" //PTR: %u %s \"%s\"\n", (unsigned int)ptrId, rgTags[ptrTag], *ptrName); 187 | } 188 | } 189 | 190 | // children 191 | 192 | #if 0 193 | for (int i = 0; i < depth; ++i) putwchar(L' '); 194 | wprintf(L" //C\n"); 195 | #endif 196 | 197 | SymbolEnumerator iter; 198 | if (iter.Find(pSymbol, SymTagNull, NULL)) { 199 | while (iter.Next()) { 200 | PrintMetaSym(*iter, uniq, depth + 1); 201 | } 202 | } 203 | 204 | // type children 205 | 206 | #if 0 207 | for (int i = 0; i < depth; ++i) putwchar(L' '); 208 | wprintf(L" //T\n"); 209 | #endif 210 | 211 | if (*type) 212 | { 213 | if (iter.Find(*type, SymTagNull, NULL)) { 214 | while (iter.Next()) { 215 | PrintMetaSym(*iter, uniq, depth + 1); 216 | } 217 | } 218 | } 219 | 220 | if (depth == 0) 221 | { 222 | wprintf(L"\n"); 223 | } 224 | } 225 | 226 | static void PrintMetaBaseClass(Bstr& udtName, IDiaSymbol *pSymbol) 227 | { 228 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/baseclass.md 229 | 230 | DWORD baseKind = 0; 231 | pSymbol->get_udtKind(&baseKind); 232 | wprintf(L"%s ", rgUdtKind[baseKind]); 233 | 234 | PrintName(pSymbol); 235 | 236 | BOOL flag; 237 | DWORD dispIndex; 238 | LONG ptrOffset; 239 | ComRef vbTableType; 240 | 241 | if ((pSymbol->get_virtualBaseClass(&flag) == S_OK) && flag) { 242 | if ((pSymbol->get_virtualBaseDispIndex(&dispIndex) == S_OK) && 243 | (pSymbol->get_virtualBasePointerOffset(&ptrOffset) == S_OK)) { 244 | 245 | wprintf(L" @vbc @vbdi=0x%X @vbpo=%ld @vbtt=", dispIndex, ptrOffset); 246 | if (pSymbol->get_virtualBaseTableType(&vbTableType) == S_OK) { 247 | PrintTypeX(*vbTableType); 248 | } 249 | else { 250 | wprintf(L"?"); 251 | } 252 | } 253 | } 254 | else { 255 | LONG offset; 256 | if (pSymbol->get_offset(&offset) == S_OK) { 257 | wprintf(L" @off=%u", (unsigned int)offset); 258 | } 259 | } 260 | 261 | ULONGLONG len; 262 | if (pSymbol->get_length(&len) == S_OK) { 263 | wprintf(L" @len=%u", (unsigned int)len); 264 | } 265 | 266 | putwchar(L'\n'); 267 | } 268 | 269 | static void PrintMetaField(Bstr& udtName, IDiaSymbol *pSymbol) 270 | { 271 | PrintLocation(pSymbol); 272 | 273 | DWORD dwDataKind; 274 | pSymbol->get_dataKind(&dwDataKind); 275 | 276 | wprintf(L", %s", rgDataKind[dwDataKind]); 277 | PrintSymbolType(pSymbol); 278 | 279 | wprintf(L", "); 280 | PrintName(pSymbol); 281 | 282 | putwchar(L'\n'); 283 | } 284 | 285 | static void PrintMetaFunction(Bstr& udtName, IDiaSymbol* pUDT, IDiaSymbol *pSymbol) 286 | { 287 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/function-debug-interface-access-sdk.md 288 | 289 | DWORD symId; 290 | pSymbol->get_symIndexId(&symId); 291 | 292 | Bstr name; 293 | pSymbol->get_name(&name); 294 | 295 | BOOL isStatic = FALSE; 296 | pSymbol->get_isStatic(&isStatic); 297 | 298 | BOOL isVirtual = FALSE; 299 | pSymbol->get_virtual(&isVirtual); 300 | 301 | BOOL isPure = FALSE; 302 | pSymbol->get_pure(&isPure); 303 | 304 | BOOL isIntro = FALSE; 305 | pSymbol->get_intro(&isIntro); 306 | 307 | DWORD access = 0; 308 | pSymbol->get_access(&access); 309 | 310 | DWORD callConv = 0; 311 | pSymbol->get_callingConvention(&callConv); 312 | 313 | ULONGLONG len = 0; 314 | pSymbol->get_length(&len); 315 | 316 | DWORD dwLocType = 0; 317 | DWORD dwRVA = 0, dwSect = 0, dwOff = 0; 318 | if (pSymbol->get_locationType(&dwLocType) == S_OK) { 319 | if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) && 320 | (pSymbol->get_addressSection(&dwSect) == S_OK) && 321 | (pSymbol->get_addressOffset(&dwOff) == S_OK)) { 322 | } 323 | } 324 | 325 | DWORD vtpo = 0; // virtual table pointer offset 326 | DWORD vfid = 0; // virtual function id in VT 327 | if (isVirtual) { 328 | GetVirtualFuncInfo(pUDT, pSymbol, vtpo, vfid); 329 | } 330 | 331 | ComRef funcType; 332 | pSymbol->get_type(&funcType); 333 | 334 | ComRef returnType; 335 | funcType->get_type(&returnType); 336 | 337 | wprintf(L"%s ", rgAccess[access]); 338 | PrintTypeX(*returnType); 339 | wprintf(L" %s(", *name); 340 | PrintFunctionArgsX(pSymbol, TRUE, TRUE); 341 | wprintf(L");"); 342 | 343 | if (isIntro) { 344 | wprintf(L" @intro"); 345 | } 346 | if (isPure) { 347 | wprintf(L" @pure"); 348 | } 349 | if (isVirtual) { 350 | wprintf(L" @virtual vtpo=%u vfid=%u", (unsigned int)vtpo, (unsigned int)vfid); 351 | } 352 | 353 | wprintf(L" @loc=%s", (dwLocType > 0 ? rgLocationTypeString[dwLocType] : L"optimized")); 354 | 355 | wprintf(L" @len=%u @rva=%u @symid=%u", (unsigned int)len, (unsigned int)dwRVA, (unsigned int)symId); 356 | 357 | //std::wstring uniq = GetUniqFunctionName(pSymbol); 358 | //wprintf(L" @uniq \"%s\"", uniq.c_str()); 359 | 360 | putwchar(L'\n'); 361 | } 362 | 363 | static void PrintMetaUDT(IDiaSymbol *pUDT) 364 | { 365 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/udt.md 366 | 367 | DWORD symTag; 368 | if (pUDT->get_symTag(&symTag) != S_OK) return; 369 | 370 | if (symTag != SymTagUDT) 371 | { 372 | DWORD symId; 373 | pUDT->get_symIndexId(&symId); 374 | 375 | Bstr name; 376 | pUDT->get_name(&name); 377 | 378 | wprintf(L"//Tag: %u %s \"%s\"\n", (unsigned int)symId, rgTags[symTag], *name); 379 | 380 | ComRef type; 381 | if (pUDT->get_type(&type) == S_OK) 382 | { 383 | DWORD typeTag; 384 | type->get_symTag(&typeTag); 385 | type->get_symIndexId(&symId); 386 | type->get_name(&name); 387 | 388 | wprintf(L"\t//type %u %s \"%s\"\n", (unsigned int)symId, rgTags[typeTag], *name); 389 | } 390 | 391 | return; 392 | } 393 | 394 | DWORD kind = 0; 395 | pUDT->get_udtKind(&kind); 396 | if (!(kind == UdtStruct || kind == UdtClass)) 397 | { 398 | return; 399 | } 400 | 401 | Bstr name; 402 | if (pUDT->get_name(&name) != S_OK) { 403 | return; 404 | } 405 | 406 | wprintf(L"//UDT: "); 407 | wprintf(L"%s", rgUdtKind[kind]); 408 | wprintf(L" %s", *name); 409 | 410 | ULONGLONG len; 411 | if (pUDT->get_length(&len) == S_OK) { 412 | wprintf(L" @len=%u", (unsigned int)len); 413 | } 414 | 415 | BOOL aligned = FALSE; 416 | pUDT->get_isDataAligned(&aligned); 417 | if (aligned) { 418 | wprintf(L" @aligned"); 419 | } 420 | 421 | ComRef enumerator; 422 | ComRef symbol; 423 | DWORD baseCount = 0; 424 | if (SUCCEEDED(pUDT->findChildren(SymTagBaseClass, NULL, nsNone, &enumerator))) 425 | { 426 | ULONG celt = 0; 427 | while (SUCCEEDED(enumerator->Next(1, &symbol, &celt)) && (celt == 1)) { baseCount++; } 428 | } 429 | if (baseCount > 1) 430 | { 431 | wprintf(L" @multibase=%u", (unsigned int)baseCount); 432 | } 433 | else 434 | { 435 | ComRef vtShape; 436 | if (pUDT->get_virtualTableShape(&vtShape) == S_OK) 437 | { 438 | DWORD vfCount = 0; 439 | vtShape->get_count(&vfCount); 440 | if (vfCount) { 441 | wprintf(L" @vfcount=%u", (unsigned int)vfCount); 442 | } 443 | } 444 | } 445 | 446 | putwchar(L'\n'); 447 | 448 | // print tags 449 | DWORD dataOff = 0; 450 | if (SUCCEEDED(pUDT->findChildren(SymTagNull, NULL, nsNone, &enumerator))) { 451 | ULONG celt = 0; 452 | while (SUCCEEDED(enumerator->Next(1, &symbol, &celt)) && (celt == 1)) { 453 | 454 | DWORD tag; 455 | symbol->get_symTag(&tag); 456 | switch (tag) 457 | { 458 | case SymTagBaseClass: 459 | { 460 | LONG baseOff = 0; 461 | ULONGLONG baseLen = 0; 462 | if (symbol->get_offset(&baseOff) == S_OK) { 463 | if (symbol->get_length(&baseLen) == S_OK) { 464 | DWORD val = (DWORD)(baseOff + baseLen); 465 | if (dataOff < val) { 466 | dataOff = val; 467 | } 468 | } 469 | } 470 | wprintf(L"\t//_Base: "); 471 | PrintMetaBaseClass(name, *symbol); 472 | break; 473 | } 474 | 475 | case SymTagVTable: 476 | { 477 | // https://github.com/MicrosoftDocs/visualstudio-docs/blob/master/docs/debugger/debug-interface-access/vtable.md 478 | wprintf(L"\t//_VTable: "); 479 | putwchar(L'\n'); 480 | break; 481 | } 482 | 483 | case SymTagFunction: 484 | { 485 | wprintf(L"\t//_Func: "); 486 | PrintMetaFunction(name, pUDT, *symbol); 487 | break; 488 | } 489 | 490 | case SymTagData: 491 | { 492 | wprintf(L"\t//_Data: "); 493 | PrintMetaField(name, *symbol); 494 | break; 495 | } 496 | 497 | default: 498 | { 499 | wprintf(L"\t//_Tag %u\n", (unsigned int)tag); 500 | break; 501 | } 502 | } 503 | } 504 | } 505 | 506 | wprintf(L"//UDT;\n\n"); 507 | } 508 | -------------------------------------------------------------------------------- /x_names.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static bool IsCompilerNamespace(const wchar_t* name) 4 | { 5 | bool res = 6 | startsWith(name, L"std::") || 7 | startsWith(name, L"boost::") || 8 | startsWith(name, L"Concurrency::") || 9 | startsWith(name, L"DirectX::") 10 | ; 11 | return res; 12 | } 13 | 14 | static bool IsCompilerPrefix(const wchar_t* name) 15 | { 16 | bool res = 17 | startsWith(name, L"_") || 18 | startsWith(name, L"$") || 19 | startsWith(name, L"_std") || 20 | startsWith(name, L"_vc_") || 21 | startsWith(name, L"_crt") || 22 | startsWith(name, L"_vcrt") || 23 | startsWith(name, L"_RTTI") 24 | ; 25 | return res; 26 | } 27 | 28 | static bool IsAllowedName(const wchar_t* name) 29 | { 30 | bool bad = 31 | IsCompilerNamespace(name) 32 | || IsCompilerPrefix(name) 33 | || startsWith(name, L"DXGI") 34 | || startsWith(name, L"IDXGI") 35 | || startsWith(name, L"D2D1") 36 | || startsWith(name, L"D3D1") 37 | || startsWith(name, L"D3DX") 38 | || startsWith(name, L"ID3D") 39 | || startsWith(name, L"CD3D") 40 | || startsWith(name, L"D3D_") 41 | || startsWith(name, L"IDirectInput") 42 | || startsWith(name, L"IDWrite") 43 | || startsWith(name, L"DWRITE") 44 | || startsWith(name, L"FMOD") 45 | || wcsstr(name, L"unnamed-tag") 46 | || wcsstr(name, L"unnamed-type") 47 | || wcsstr(name, L"unnamed-enum") 48 | || wcsstr(name, L"lambda_") 49 | ; 50 | return !bad; 51 | } 52 | 53 | static bool IsTemplateClass(const wchar_t* name) 54 | { 55 | return wcsstr(name, L"<") ? true : false; 56 | } 57 | 58 | inline std::wstring fixEnumName(const std::wstring& name) 59 | { 60 | std::wstring fixed(name); 61 | replaceAll(fixed, L"::", L"_"); 62 | return fixed; 63 | } 64 | 65 | inline std::wstring fixName(const std::wstring& name) 66 | { 67 | // TODO: THIS IS SPARTA!!! 68 | std::wstring fixed(name); 69 | replaceAll(fixed, L"std::", L"stdXX"); 70 | replaceAll(fixed, L"Concurrency::", L"ConcurrencyXX"); 71 | replaceAll(fixed, L"DirectX::", L"DirectXXX"); 72 | replaceAll(fixed, L"::", L"_"); 73 | replaceAll(fixed, L"stdXX", L"std::"); 74 | replaceAll(fixed, L"ConcurrencyXX", L"Concurrency::"); 75 | replaceAll(fixed, L"DirectXXX", L"DirectX::"); 76 | return fixed; 77 | } 78 | -------------------------------------------------------------------------------- /x_print.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // forward decl 4 | static void PrintTypeX(IDiaSymbol *pSymbol, std::wstring* dst = NULL); 5 | 6 | static void wprintfX(std::wstring* dst, const wchar_t* format, ...) 7 | { 8 | wchar_t buf[1024] = { 0 }; 9 | va_list args; 10 | va_start(args, format); 11 | const int count = _vsnwprintf_s(buf, _countof(buf) - 1, _TRUNCATE, format, args); 12 | va_end(args); 13 | 14 | if (count > 0) 15 | { 16 | if (dst) dst->append(buf); 17 | else wprintf(L"%s", buf); 18 | } 19 | } 20 | 21 | static void PrintVariantX(VARIANT var, std::wstring* dst = NULL) 22 | { 23 | switch (var.vt) { 24 | case VT_UI1: 25 | case VT_I1: 26 | wprintfX(dst, L" 0x%X", var.bVal); 27 | break; 28 | 29 | case VT_I2: 30 | case VT_UI2: 31 | case VT_BOOL: 32 | wprintfX(dst, L" 0x%X", var.iVal); 33 | break; 34 | 35 | case VT_I4: 36 | case VT_UI4: 37 | case VT_INT: 38 | case VT_UINT: 39 | case VT_ERROR: 40 | wprintfX(dst, L" 0x%X", var.lVal); 41 | break; 42 | 43 | case VT_R4: 44 | wprintfX(dst, L" %g", var.fltVal); 45 | break; 46 | 47 | case VT_R8: 48 | wprintfX(dst, L" %g", var.dblVal); 49 | break; 50 | 51 | case VT_BSTR: 52 | wprintfX(dst, L" \"%s\"", var.bstrVal); 53 | break; 54 | 55 | default: 56 | wprintfX(dst, L" ??"); 57 | } 58 | } 59 | 60 | static void PrintNameX(IDiaSymbol *pSymbol, std::wstring* dst = NULL) 61 | { 62 | BSTR bstrName; 63 | BSTR bstrUndName; 64 | 65 | if (pSymbol->get_name(&bstrName) != S_OK) { 66 | wprintfX(dst, L"(none)"); 67 | return; 68 | } 69 | 70 | if (pSymbol->get_undecoratedName(&bstrUndName) == S_OK) { 71 | if (wcscmp(bstrName, bstrUndName) == 0) { 72 | wprintfX(dst, L"%s", bstrName); 73 | } 74 | else { 75 | wprintfX(dst, L"%s(%s)", bstrUndName, bstrName); 76 | } 77 | SysFreeString(bstrUndName); 78 | } 79 | else { 80 | wprintfX(dst, L"%s", bstrName); 81 | } 82 | 83 | SysFreeString(bstrName); 84 | } 85 | 86 | static void PrintBaseTypeX(IDiaSymbol *pSymbol, std::wstring* dst = NULL) 87 | { 88 | DWORD dwInfo; 89 | if (pSymbol->get_baseType(&dwInfo) != S_OK) return; 90 | 91 | ULONGLONG ulLen = 0; 92 | pSymbol->get_length(&ulLen); 93 | 94 | switch (dwInfo) { 95 | case btUInt: 96 | wprintfX(dst, L"unsigned "); 97 | // fall through 98 | 99 | case btInt: 100 | switch (ulLen) { 101 | case 1: 102 | if (dwInfo == btInt) { 103 | wprintfX(dst, L"signed "); 104 | } 105 | wprintfX(dst, L"char"); 106 | break; 107 | 108 | case 2: 109 | wprintfX(dst, L"short"); 110 | break; 111 | 112 | case 4: 113 | wprintfX(dst, L"int"); 114 | break; 115 | 116 | case 8: 117 | wprintfX(dst, L"__int64"); 118 | break; 119 | } 120 | dwInfo = 0xFFFFFFFF; 121 | break; 122 | 123 | case btFloat: 124 | switch (ulLen) { 125 | case 4: 126 | wprintfX(dst, L"float"); 127 | break; 128 | case 8: 129 | wprintfX(dst, L"double"); 130 | break; 131 | } 132 | dwInfo = 0xFFFFFFFF; 133 | break; 134 | } 135 | 136 | if (dwInfo != 0xFFFFFFFF) { 137 | wprintfX(dst, L"%s", rgBaseType[dwInfo]); 138 | } 139 | } 140 | 141 | static void PrintLocationX(IDiaSymbol *pSymbol, std::wstring* dst = NULL) 142 | { 143 | DWORD dwLocType; 144 | DWORD dwRVA, dwSect, dwOff, dwReg, dwBitPos, dwSlot; 145 | LONG lOffset; 146 | ULONGLONG ulLen; 147 | VARIANT vt = { VT_EMPTY }; 148 | 149 | if (pSymbol->get_locationType(&dwLocType) != S_OK) { 150 | wprintfX(dst, L"optmized"); 151 | return; 152 | } 153 | 154 | switch (dwLocType) { 155 | case LocIsStatic: 156 | if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) && 157 | (pSymbol->get_addressSection(&dwSect) == S_OK) && 158 | (pSymbol->get_addressOffset(&dwOff) == S_OK)) { 159 | wprintfX(dst, L"%s, [%08X][%04X:%08X]", (rgLocationTypeString, dwLocType), dwRVA, dwSect, dwOff); 160 | } 161 | break; 162 | 163 | case LocIsTLS: 164 | case LocInMetaData: 165 | case LocIsIlRel: 166 | if ((pSymbol->get_relativeVirtualAddress(&dwRVA) == S_OK) && 167 | (pSymbol->get_addressSection(&dwSect) == S_OK) && 168 | (pSymbol->get_addressOffset(&dwOff) == S_OK)) { 169 | wprintfX(dst, L"%s, [%08X][%04X:%08X]", (rgLocationTypeString, dwLocType), dwRVA, dwSect, dwOff); 170 | } 171 | break; 172 | 173 | case LocIsRegRel: 174 | if ((pSymbol->get_registerId(&dwReg) == S_OK) && 175 | (pSymbol->get_offset(&lOffset) == S_OK)) { 176 | wprintfX(dst, L"%s Relative, [%08X]", SzNameC7Reg((USHORT)dwReg), lOffset); 177 | } 178 | break; 179 | 180 | case LocIsThisRel: 181 | if (pSymbol->get_offset(&lOffset) == S_OK) { 182 | wprintfX(dst, L"this+0x%X", lOffset); 183 | } 184 | break; 185 | 186 | case LocIsBitField: 187 | if ((pSymbol->get_offset(&lOffset) == S_OK) && 188 | (pSymbol->get_bitPosition(&dwBitPos) == S_OK) && 189 | (pSymbol->get_length(&ulLen) == S_OK)) { 190 | wprintfX(dst, L"this(bf)+0x%X:0x%X len(0x%X)", lOffset, dwBitPos, (ULONG)ulLen); 191 | } 192 | break; 193 | 194 | case LocIsEnregistered: 195 | if (pSymbol->get_registerId(&dwReg) == S_OK) { 196 | wprintfX(dst, L"enregistered %s", SzNameC7Reg((USHORT)dwReg)); 197 | } 198 | break; 199 | 200 | case LocIsSlot: 201 | if (pSymbol->get_slot(&dwSlot) == S_OK) { 202 | wprintfX(dst, L"%s, [%08X]", (rgLocationTypeString, dwLocType), dwSlot); 203 | } 204 | break; 205 | 206 | case LocIsConstant: 207 | wprintfX(dst, L"constant"); 208 | 209 | if (pSymbol->get_value(&vt) == S_OK) { 210 | PrintVariantX(vt, dst); 211 | VariantClear((VARIANTARG *)&vt); 212 | } 213 | break; 214 | 215 | case LocIsNull: 216 | break; 217 | 218 | default: 219 | wprintfX(dst, L"Error - invalid location type: 0x%X", dwLocType); 220 | break; 221 | } 222 | } 223 | 224 | static void PrintPointerTypeX(IDiaSymbol *pSymbol, std::wstring* dst = NULL, BOOL replaceRefWithPtr = FALSE) 225 | { 226 | ComRef pBaseType; 227 | if (pSymbol->get_type(&pBaseType) != S_OK) return; 228 | 229 | Bstr name; 230 | pSymbol->get_name(&name); 231 | 232 | BOOL isRef = FALSE; 233 | pSymbol->get_reference(&isRef); 234 | 235 | BOOL isConst = FALSE; 236 | pSymbol->get_constType(&isConst); 237 | 238 | DWORD baseTypeTag = 0; 239 | pBaseType->get_symTag(&baseTypeTag); 240 | 241 | BOOL isBaseConst = FALSE; 242 | pBaseType->get_constType(&isBaseConst); 243 | 244 | #if 0 245 | if (baseTypeTag == SymTagUDT && !isRef) 246 | { 247 | DWORD kind = 0; 248 | pBaseType->get_udtKind(&kind); 249 | wprintfX(dst, L"%s ", rgUdtKind[kind]); 250 | } 251 | #endif 252 | 253 | if (isBaseConst) { 254 | wprintfX(dst, L"const "); 255 | } 256 | 257 | if (baseTypeTag == SymTagFunctionType) 258 | { 259 | wprintfX(dst, L"void"); 260 | } 261 | else 262 | { 263 | PrintTypeX(*pBaseType, dst); 264 | } 265 | 266 | if (isRef) { 267 | if (replaceRefWithPtr) 268 | wprintfX(dst, L" *"); 269 | else 270 | wprintfX(dst, L" &"); 271 | } 272 | else { 273 | wprintfX(dst, L" *"); 274 | } 275 | 276 | #if 0 277 | BOOL bSet; 278 | if ((pSymbol->get_constType(&bSet) == S_OK) && bSet) { 279 | wprintfX(dst, L" const"); 280 | } 281 | 282 | if ((pSymbol->get_volatileType(&bSet) == S_OK) && bSet) { 283 | wprintfX(dst, L" volatile"); 284 | } 285 | 286 | if ((pSymbol->get_unalignedType(&bSet) == S_OK) && bSet) { 287 | wprintfX(dst, L" __unaligned"); 288 | } 289 | #endif 290 | } 291 | 292 | static void PrintBoundX(IDiaSymbol *pSymbol, std::wstring* dst = NULL) 293 | { 294 | DWORD dwTag = 0; 295 | DWORD dwKind; 296 | 297 | if (pSymbol->get_symTag(&dwTag) != S_OK) { 298 | wprintfX(dst, L"ERROR - PrintBound() get_symTag"); 299 | return; 300 | } 301 | 302 | if (pSymbol->get_locationType(&dwKind) != S_OK) { 303 | wprintfX(dst, L"ERROR - PrintBound() get_locationType"); 304 | return; 305 | } 306 | 307 | if (dwTag == SymTagData && dwKind == LocIsConstant) { 308 | VARIANT v = { VT_EMPTY }; 309 | if (pSymbol->get_value(&v) == S_OK) { 310 | PrintVariantX(v, dst); 311 | VariantClear((VARIANTARG *)&v); 312 | } 313 | } 314 | else { 315 | PrintNameX(pSymbol, dst); 316 | } 317 | } 318 | 319 | static void PrintArraySizeX(IDiaSymbol *pSymbol, std::wstring* dst = NULL) 320 | { 321 | DWORD symTag; 322 | pSymbol->get_symTag(&symTag); 323 | if (symTag != SymTagArrayType) { 324 | return; 325 | } 326 | 327 | ComRef baseType; 328 | if (pSymbol->get_type(&baseType) != S_OK) { 329 | return; 330 | } 331 | 332 | PrintArraySizeX(*baseType, dst); 333 | 334 | SymbolEnumerator child; 335 | DWORD dwRank; 336 | LONG count; 337 | 338 | if (pSymbol->get_rank(&dwRank) == S_OK) { 339 | if (child.Find(pSymbol, SymTagDimension, NULL)) { 340 | while (child.Next()) { 341 | 342 | wprintfX(dst, L"["); 343 | ComRef bound; 344 | if (child->get_lowerBound(&bound) == S_OK) { 345 | PrintBoundX(*bound, dst); 346 | wprintfX(dst, L".."); 347 | } 348 | 349 | if (child->get_upperBound(&bound) == S_OK) { 350 | PrintBoundX(*bound, dst); 351 | } 352 | wprintfX(dst, L"]"); 353 | } 354 | } 355 | } 356 | else if (child.Find(pSymbol, SymTagCustomType, NULL) && (child._enumerator->get_Count(&count) == S_OK) && (count > 0)) { 357 | while (child.Next()) { 358 | 359 | wprintfX(dst, L"["); 360 | PrintTypeX(*child, dst); 361 | wprintfX(dst, L"]"); 362 | } 363 | } 364 | else { 365 | DWORD dwCountElems = 0; 366 | ULONGLONG ulLenArray = 0; 367 | ULONGLONG ulLenElem = 0; 368 | 369 | if (pSymbol->get_count(&dwCountElems) == S_OK) { 370 | wprintfX(dst, L"[%u]", (unsigned int)dwCountElems); 371 | } 372 | else if ((pSymbol->get_length(&ulLenArray) == S_OK) && (baseType->get_length(&ulLenElem) == S_OK)) { 373 | if (ulLenElem == 0) { 374 | wprintfX(dst, L"[%u]", (unsigned int)ulLenArray); 375 | } 376 | else { 377 | wprintfX(dst, L"[%u]", (unsigned int)ulLenArray / (unsigned int)ulLenElem); 378 | } 379 | } 380 | } 381 | } 382 | 383 | static void PrintCustomTypeX(IDiaSymbol *pSymbol, std::wstring* dst = NULL) 384 | { 385 | DWORD idOEM, idOEMSym; 386 | DWORD cbData = 0; 387 | DWORD count; 388 | 389 | if (pSymbol->get_oemId(&idOEM) == S_OK) { 390 | wprintfX(dst, L"OEMId = %X, ", idOEM); 391 | } 392 | 393 | if (pSymbol->get_oemSymbolId(&idOEMSym) == S_OK) { 394 | wprintfX(dst, L"SymbolId = %X, ", idOEMSym); 395 | } 396 | 397 | if (pSymbol->get_types(0, &count, NULL) == S_OK) { 398 | IDiaSymbol** rgpDiaSymbols = (IDiaSymbol**)_alloca(sizeof(IDiaSymbol *) * count); 399 | 400 | if (pSymbol->get_types(count, &count, rgpDiaSymbols) == S_OK) { 401 | for (ULONG i = 0; i < count; i++) { 402 | 403 | PrintTypeX(rgpDiaSymbols[i], dst); 404 | rgpDiaSymbols[i]->Release(); 405 | } 406 | } 407 | } 408 | 409 | if ((pSymbol->get_dataBytes(cbData, &cbData, NULL) == S_OK) && (cbData != 0)) { 410 | 411 | wprintfX(dst, L", Data: "); 412 | 413 | BYTE *pbData = new BYTE[cbData]; 414 | pSymbol->get_dataBytes(cbData, &cbData, pbData); 415 | 416 | for (ULONG i = 0; i < cbData; i++) { 417 | wprintfX(dst, L"0x%02X ", pbData[i]); 418 | } 419 | 420 | delete[] pbData; 421 | } 422 | } 423 | 424 | static void PrintFunctionArgsX(IDiaSymbol *pFunc, BOOL genArgTypes = TRUE, BOOL genArgNames = FALSE, const wchar_t* pthisType = NULL, std::wstring* dst = NULL) 425 | { 426 | if (!genArgTypes && !genArgNames) return; 427 | 428 | int argId = 0; 429 | 430 | if (pthisType) { 431 | if (genArgTypes) { 432 | wprintfX(dst, L"%s *pthis", pthisType); 433 | } 434 | else { 435 | wprintfX(dst, L"this"); 436 | } 437 | argId++; 438 | } 439 | 440 | int dataCount = 0; 441 | ComRef children; 442 | if (SUCCEEDED(pFunc->findChildren(SymTagData, NULL, nsNone, &children))) { 443 | ComRef child; 444 | ULONG celt = 0; 445 | while (SUCCEEDED(children->Next(1, &child, &celt)) && (celt == 1)) { 446 | 447 | DWORD argKind = 0; 448 | child->get_dataKind(&argKind); 449 | if (argKind == DataIsParam) { 450 | 451 | ComRef childType; 452 | if (child->get_type(&childType) == S_OK) { 453 | 454 | if (argId) { 455 | wprintfX(dst, L", "); 456 | } 457 | if (genArgTypes) { 458 | PrintTypeX(*childType, dst); 459 | } 460 | if (genArgNames) { 461 | if (genArgTypes) { 462 | wprintfX(dst, L" "); 463 | } 464 | Bstr name; 465 | child->get_name(&name); 466 | wprintfX(dst, L"%s", *name); 467 | } 468 | argId++; 469 | } 470 | dataCount++; 471 | } 472 | } 473 | } 474 | 475 | if (!dataCount) { 476 | ComRef funcType; 477 | pFunc->get_type(&funcType); 478 | 479 | if (SUCCEEDED(funcType->findChildren(SymTagFunctionArgType, NULL, nsNone, &children))) { 480 | ComRef child; 481 | ULONG celt = 0; 482 | while (SUCCEEDED(children->Next(1, &child, &celt)) && (celt == 1)) { 483 | 484 | ComRef childType; 485 | if (child->get_type(&childType) == S_OK) { 486 | if (argId) { 487 | wprintfX(dst, L", "); 488 | } 489 | if (genArgTypes) { 490 | PrintTypeX(*childType, dst); 491 | } 492 | if (genArgNames) { 493 | if (genArgTypes) { 494 | //wprintfX(dst, L" "); 495 | } 496 | wprintfX(dst, L" _arg%d", argId); 497 | } 498 | argId++; 499 | } 500 | } 501 | } 502 | } 503 | } 504 | 505 | static void PrintTypeX(IDiaSymbol *pSymbol, std::wstring* dst) 506 | { 507 | DWORD dwTag; 508 | if (pSymbol->get_symTag(&dwTag) != S_OK) return; 509 | 510 | #if 0 511 | if (dwTag != SymTagPointerType) 512 | { 513 | BOOL bSet; 514 | if ((pSymbol->get_constType(&bSet) == S_OK) && bSet) { 515 | wprintfX(dst, L"const "); 516 | } 517 | if ((pSymbol->get_volatileType(&bSet) == S_OK) && bSet) { 518 | wprintfX(dst, L"volatile "); 519 | } 520 | if ((pSymbol->get_unalignedType(&bSet) == S_OK) && bSet) { 521 | wprintfX(dst, L"__unaligned "); 522 | } 523 | } 524 | #endif 525 | 526 | switch (dwTag) 527 | { 528 | case SymTagUDT: 529 | { 530 | Bstr symName; 531 | pSymbol->get_name(&symName); 532 | std::wstring fixedName(fixName(*symName)); 533 | 534 | wprintfX(dst, L"%s", fixedName.c_str()); 535 | break; 536 | } 537 | 538 | case SymTagEnum: 539 | { 540 | Bstr symName; 541 | pSymbol->get_name(&symName); 542 | std::wstring fixedName(fixEnumName(*symName)); 543 | 544 | wprintfX(dst, L"%s", fixedName.c_str()); 545 | break; 546 | } 547 | 548 | case SymTagBaseType: 549 | { 550 | PrintBaseTypeX(pSymbol, dst); 551 | break; 552 | } 553 | 554 | case SymTagPointerType: 555 | { 556 | PrintPointerTypeX(pSymbol, dst); 557 | break; 558 | } 559 | 560 | case SymTagArrayType: 561 | { 562 | ComRef baseType; 563 | pSymbol->get_type(&baseType); 564 | 565 | PrintTypeX(*baseType, dst); 566 | break; 567 | } 568 | 569 | case SymTagCustomType: 570 | { 571 | PrintCustomTypeX(pSymbol, dst); 572 | break; 573 | } 574 | 575 | case SymTagTypedef: 576 | { 577 | PrintNameX(pSymbol, dst); 578 | break; 579 | } 580 | 581 | case SymTagData: 582 | { 583 | PrintLocationX(pSymbol, dst); 584 | break; 585 | } 586 | } 587 | } 588 | 589 | static void PrintFakeRefsX(IDiaSymbol *pUDT, std::wstring* dst = NULL) 590 | { 591 | int count = 0; 592 | SymbolEnumerator symbol; 593 | if (symbol.Find(pUDT, SymTagData, NULL)) { 594 | while (symbol.Next()) { 595 | 596 | DWORD dwDataKind; 597 | symbol->get_dataKind(&dwDataKind); 598 | 599 | if (dwDataKind == DataIsMember) 600 | { 601 | ComRef fieldType; 602 | symbol->get_type(&fieldType); 603 | 604 | BOOL isRef = FALSE; 605 | fieldType->get_reference(&isRef); 606 | 607 | if (isRef) { 608 | 609 | if (!count) wprintfX(dst, L" : "); 610 | else wprintfX(dst, L", "); 611 | 612 | Bstr fieldName; 613 | symbol->get_name(&fieldName); 614 | wprintfX(dst, L"%s(*((", *fieldName); 615 | 616 | ComRef baseType; 617 | fieldType->get_type(&baseType); 618 | Bstr baseName; 619 | baseType->get_name(&baseName); 620 | 621 | PrintTypeX(*baseType); 622 | wprintfX(dst, L"*)NULL))"); 623 | 624 | ++count; 625 | } 626 | } 627 | } 628 | } 629 | } 630 | -------------------------------------------------------------------------------- /x_ripper.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ACHTUNG!!! COMPLETELY BRAINDAMAGED SHITCODE!!! 3 | // 4 | 5 | #include "stdafx.h" 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "Dia2Dump.h" 21 | #include "PrintSymbol.h" 22 | 23 | #include "x_str.h" 24 | #include "x_common.h" 25 | #include "x_names.h" 26 | #include "x_print.h" 27 | #include "x_meta.h" 28 | #include "x_udt.h" 29 | 30 | // [CONFIG] 31 | //#define GEN_DUMMY_CTOR 32 | #define GEN_VFUNC_REDIR 33 | //#define GEN_VFUNC_BODY 34 | 35 | #include "x_cpp_enum.h" 36 | #include "x_cpp_proxy.h" 37 | #include "x_cpp_gen_file.h" 38 | 39 | void RipPdb(IDiaSymbol *pGlobal, int argc, wchar_t *argv[]) 40 | { 41 | // USAGE: dia2dump.exe -rip [flags] ... 42 | 43 | BOOL bPrintNamesOnly = FALSE; 44 | BOOL bPrintCppProxy = FALSE; 45 | BOOL bGenerateCppFiles = FALSE; 46 | BOOL bIncludeInternals = FALSE; 47 | BOOL bIncludeTemplates = FALSE; 48 | BOOL bSymbols = FALSE; 49 | BOOL bMeta = FALSE; 50 | BOOL bGuardObjects = FALSE; 51 | BOOL bZeroInitialize = FALSE; 52 | BOOL bExpandDeps = FALSE; 53 | BOOL bResolveDeps = FALSE; 54 | std::wstring filter; 55 | 56 | if (argc > 3) { 57 | for (int i = 2; i < argc - 1; ++i) { 58 | if (!wcscmp(argv[i], L"-printNamesOnly")) bPrintNamesOnly = TRUE; 59 | else if (!wcscmp(argv[i], L"-printCppProxy")) bPrintCppProxy = TRUE; 60 | else if (!wcscmp(argv[i], L"-genCppFiles")) bGenerateCppFiles = TRUE; 61 | else if (!wcscmp(argv[i], L"-ii")) bIncludeInternals = TRUE; 62 | else if (!wcscmp(argv[i], L"-it")) bIncludeTemplates = TRUE; 63 | else if (!wcscmp(argv[i], L"-s")) bSymbols = TRUE; 64 | else if (!wcscmp(argv[i], L"-m")) bMeta = TRUE; 65 | else if (!wcscmp(argv[i], L"-g")) bGuardObjects = TRUE; 66 | else if (!wcscmp(argv[i], L"-zi")) bZeroInitialize = TRUE; 67 | else if (!wcscmp(argv[i], L"-d")) bExpandDeps = TRUE; 68 | else if (!wcscmp(argv[i], L"-rd")) bResolveDeps = TRUE; 69 | else if (!wcscmp(argv[i], L"-names") && (i + 1 < argc - 1)) { filter = argv[i + 1]; i++; } 70 | } 71 | } 72 | 73 | //MessageBoxA(NULL, "_debug", "_debug", MB_OK); 74 | 75 | auto graph = GetUdtGraph(pGlobal); 76 | 77 | UdtGraphPtr filtered; 78 | if (filter.empty()) { 79 | filtered = graph; 80 | } 81 | else { 82 | filtered = FilterUdtGraph(graph, filter, bExpandDeps); 83 | } 84 | 85 | ResolvedUdtGraphPtr resolved; 86 | if (bResolveDeps) { 87 | resolved = ResolveDeps(filtered); 88 | } 89 | else { 90 | resolved = SortBySymId(filtered); 91 | } 92 | 93 | if (bPrintCppProxy) { 94 | wprintf(L"// ### AUTO-GENERATED ###\n\n"); 95 | CppPrintEnums(pGlobal, resolved); 96 | CppProxyPrintForwardDecl(pGlobal, resolved, graph); 97 | } 98 | 99 | if (bGenerateCppFiles) { 100 | CppGenEnums(pGlobal, resolved); 101 | } 102 | 103 | for (auto& node : resolved->nodes) { 104 | if ((bIncludeInternals || IsAllowedName(node->name.c_str())) && (bIncludeTemplates || !IsTemplateClass(node->name.c_str()))) { 105 | if (bPrintNamesOnly) { 106 | wprintf(L"%s\n", node->name.c_str()); 107 | } 108 | else { 109 | if (bSymbols) { 110 | std::unordered_set uniq; 111 | PrintMetaSym(*node->symbol, uniq); 112 | } 113 | if (bMeta) { 114 | PrintMetaUDT(*node->symbol); 115 | } 116 | if (bPrintCppProxy) { 117 | CppProxyPrintUDT(*node->symbol, bGuardObjects, bZeroInitialize); 118 | } 119 | if (bGenerateCppFiles) { 120 | CppGenClass(pGlobal, *node->symbol, node, resolved, graph); 121 | } 122 | } 123 | } 124 | } 125 | 126 | return; 127 | } 128 | -------------------------------------------------------------------------------- /x_str.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // trim from start (in place) 4 | static inline void ltrim(std::wstring &s) { 5 | s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { 6 | return !std::isspace(ch); 7 | })); 8 | } 9 | 10 | // trim from end (in place) 11 | static inline void rtrim(std::wstring &s) { 12 | s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { 13 | return !std::isspace(ch); 14 | }).base(), s.end()); 15 | } 16 | 17 | // trim from both ends (in place) 18 | static inline void trim(std::wstring &s) { 19 | ltrim(s); 20 | rtrim(s); 21 | } 22 | 23 | // trim from start (copying) 24 | static inline std::wstring ltrim_copy(std::wstring s) { 25 | ltrim(s); 26 | return s; 27 | } 28 | 29 | // trim from end (copying) 30 | static inline std::wstring rtrim_copy(std::wstring s) { 31 | rtrim(s); 32 | return s; 33 | } 34 | 35 | // trim from both ends (copying) 36 | static inline std::wstring trim_copy(std::wstring s) { 37 | trim(s); 38 | return s; 39 | } 40 | 41 | static inline bool replace(std::wstring& str, const std::wstring& from, const std::wstring& to) { 42 | size_t start_pos = str.find(from); 43 | if (start_pos == std::wstring::npos) 44 | return false; 45 | str.replace(start_pos, from.length(), to); 46 | return true; 47 | } 48 | 49 | static inline void replaceAll(std::wstring& str, const std::wstring& from, const std::wstring& to) { 50 | if (from.empty()) 51 | return; 52 | size_t start_pos = 0; 53 | while ((start_pos = str.find(from, start_pos)) != std::wstring::npos) { 54 | str.replace(start_pos, from.length(), to); 55 | start_pos += to.length(); 56 | } 57 | } 58 | 59 | static inline std::vector split(const std::wstring& input, const std::wstring& regex) { 60 | std::wregex re(regex); 61 | std::wsregex_token_iterator first{ input.begin(), input.end(), re, -1 }, last; 62 | return{ first, last }; 63 | } 64 | 65 | static inline bool startsWith(const std::wstring& s, const std::wstring& prefix) { 66 | return s.size() >= prefix.size() && s.compare(0, prefix.size(), prefix) == 0; 67 | } 68 | 69 | static inline bool startsWith(const wchar_t* s, const wchar_t* prefix) { 70 | const size_t slen = wcslen(s); 71 | const size_t plen = wcslen(prefix); 72 | if (plen > slen) return false; 73 | return (wcsncmp(s, prefix, plen) == 0); 74 | } 75 | 76 | static inline bool endsWith(const std::wstring& s, wchar_t ch) { 77 | const size_t n = s.size(); 78 | return ((n > 0) && (s[n - 1] == ch)); 79 | } 80 | 81 | static inline void removePrefix(std::wstring& str, const std::wstring& prefix) { 82 | //auto pos = str.find_first_of(prefix); 83 | auto pos = str.find(prefix); 84 | if ((pos != std::wstring::npos) && (pos + prefix.length() < str.length())) { 85 | std::wstring tmp(str.substr(pos + prefix.length())); 86 | str = tmp; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /x_udt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct UdtNode; 4 | typedef std::shared_ptr UdtNodePtr; 5 | 6 | static inline void insert(std::unordered_map& map, const std::wstring& name, UdtNodePtr node) { 7 | map.insert(std::pair(name, node)); 8 | } 9 | 10 | struct UdtNode 11 | { 12 | ComRef symbol; 13 | DWORD id; 14 | std::wstring name; 15 | std::unordered_map > dep_s; 16 | std::unordered_map dep_n; 17 | }; 18 | 19 | struct UdtGraph 20 | { 21 | std::unordered_map nodes; 22 | 23 | inline bool contains(const std::wstring& name) const { 24 | return (nodes.find(name) != nodes.end()); 25 | } 26 | 27 | inline void insert(const std::wstring& name, UdtNodePtr node) { 28 | ::insert(nodes, name, node); 29 | } 30 | 31 | inline void insert(UdtNodePtr node) { 32 | insert(node->name, node); 33 | } 34 | }; 35 | typedef std::shared_ptr UdtGraphPtr; 36 | 37 | struct ResolvedUdtGraph 38 | { 39 | std::vector nodes; 40 | 41 | #if defined(_DEBUG) 42 | std::vector names; 43 | #endif 44 | }; 45 | typedef std::shared_ptr ResolvedUdtGraphPtr; 46 | 47 | // 48 | // PARSER 49 | // 50 | 51 | static size_t find_end_scope(const std::wstring& s, size_t pos) 52 | { 53 | size_t depth = 1; 54 | size_t len = s.length(); 55 | for (size_t i = pos + 1; i < len; ++i) 56 | { 57 | if (s[i] == '<') depth++; 58 | else if (s[i] == '>') depth--; 59 | if (depth == 0) 60 | { 61 | return i; 62 | } 63 | } 64 | return s.npos; 65 | } 66 | 67 | void parse_cpp_type(const std::wstring& input, std::unordered_set& tags, int depth = 0) 68 | { 69 | //wprintf(L"parse: %s\n", input.c_str()); 70 | std::wstring s(input); 71 | for (;;) 72 | { 73 | auto p1 = s.find_first_of(L'<'); 74 | if (p1 != s.npos) 75 | { 76 | auto comma = s.find_first_of(L','); 77 | if (comma != s.npos && comma < p1) 78 | { 79 | auto inner = s.substr(0, comma); 80 | trim(inner); 81 | if (!inner.empty()) 82 | { 83 | parse_cpp_type(inner, tags, depth + 1); 84 | } 85 | 86 | s = s.substr(comma + 1); 87 | } 88 | else 89 | { 90 | auto p2 = find_end_scope(s, p1); 91 | if (p2 != s.npos) 92 | { 93 | auto tag = s.substr(0, p2 + 1); 94 | trim(tag); 95 | if (!tag.empty()) 96 | { 97 | if (tags.find(tag) == tags.end()) 98 | { 99 | //wprintf(L"tag: %s\n", tag.c_str()); 100 | tags.insert(tag); 101 | } 102 | } 103 | 104 | auto inner = s.substr(p1 + 1, p2 - p1 - 1); 105 | trim(inner); 106 | if (!inner.empty()) 107 | { 108 | parse_cpp_type(inner, tags, depth + 1); 109 | } 110 | 111 | s = s.substr(p2 + 1); 112 | } 113 | } 114 | } 115 | else 116 | { 117 | auto parts = split(s, L","); 118 | for (auto& tag : parts) 119 | { 120 | trim(tag); 121 | if (!tag.empty()) 122 | { 123 | if (tags.find(tag) == tags.end()) 124 | { 125 | //wprintf(L"tag: %s\n", tag.c_str()); 126 | tags.insert(tag); 127 | } 128 | } 129 | } 130 | break; 131 | } 132 | } 133 | 134 | return; 135 | } 136 | 137 | // 138 | // GET DEPS 139 | // 140 | 141 | static void ProcessDepType(IDiaSymbol* global, std::unordered_map >& deps, const wchar_t* cppType) 142 | { 143 | std::unordered_set tags; 144 | parse_cpp_type(cppType, tags); 145 | 146 | for (auto& tag : tags) { 147 | if (IsAllowedName(tag.c_str())) { 148 | 149 | if (deps.find(tag) == deps.end()) { 150 | auto sym = FindSymbol(global, SymTagNull, tag.c_str()); 151 | deps.insert(std::pair >(tag, sym)); 152 | } 153 | } 154 | } 155 | } 156 | 157 | static void ProcessDepType(IDiaSymbol* global, std::unordered_map >& deps, ComRef& sym) 158 | { 159 | DWORD symTag; 160 | if (sym->get_symTag(&symTag) != S_OK) return; 161 | 162 | switch (symTag) 163 | { 164 | case SymTagEnum: 165 | case SymTagUDT: 166 | { 167 | Bstr name; 168 | sym->get_name(&name); 169 | ProcessDepType(global, deps, *name); 170 | break; 171 | } 172 | 173 | case SymTagPointerType: 174 | { 175 | BOOL isRef = FALSE; 176 | sym->get_reference(&isRef); 177 | { 178 | #if defined(_DEBUG) 179 | Bstr name; 180 | sym->get_name(&name); 181 | #endif 182 | 183 | ComRef ptrType; 184 | if (sym->get_type(&ptrType) == S_OK) { 185 | 186 | DWORD ptrTypeTag = 0; 187 | ptrType->get_symTag(&ptrTypeTag); 188 | 189 | if (ptrTypeTag == SymTagUDT || ptrTypeTag == SymTagEnum) { 190 | 191 | Bstr typeName; 192 | if (ptrType->get_name(&typeName) == S_OK && wcslen(*typeName) > 0) { 193 | 194 | std::wstring argt; 195 | if (isRef) { 196 | argt.assign(*typeName); 197 | } 198 | else { 199 | //DWORD kind = 0; 200 | //ptrType->get_udtKind(&kind); 201 | //argt.append(rgUdtKind[kind]); 202 | //argt.append(L" "); 203 | argt.append(*typeName); 204 | argt.append(L" *"); 205 | } 206 | 207 | ProcessDepType(global, deps, argt.c_str()); 208 | } 209 | } 210 | } 211 | } 212 | break; 213 | } 214 | 215 | case SymTagArrayType: 216 | { 217 | ComRef arrType; 218 | if (sym->get_type(&arrType) == S_OK) { 219 | ProcessDepType(global, deps, arrType); 220 | } 221 | break; 222 | } 223 | } 224 | 225 | return; 226 | } 227 | 228 | static void GetUdtDeps(IDiaSymbol *pGlobal, IDiaSymbol *pUDT, std::unordered_map >& deps) 229 | { 230 | DWORD symTag; 231 | if (pUDT->get_symTag(&symTag) != S_OK) return; 232 | if (symTag != SymTagUDT) return; 233 | 234 | Bstr udtName; 235 | pUDT->get_name(&udtName); 236 | 237 | SymbolEnumerator iter; 238 | 239 | // base class 240 | { 241 | if (iter.Find(pUDT, SymTagBaseClass, NULL)) { 242 | while (iter.Next()) { 243 | 244 | Bstr name; 245 | iter->get_name(&name); 246 | std::wstring sname(*name); 247 | 248 | if (deps.find(sname) == deps.end()) { 249 | deps.insert(std::pair >(sname, iter.ref())); 250 | } 251 | 252 | GetUdtDeps(pGlobal, *iter, deps); 253 | } 254 | } 255 | } 256 | 257 | // data 258 | { 259 | if (iter.Find(pUDT, SymTagData, NULL)) { 260 | while (iter.Next()) { 261 | 262 | DWORD dataKind; 263 | iter->get_dataKind(&dataKind); 264 | 265 | if (dataKind == DataIsMember) { 266 | 267 | ComRef fieldType; 268 | if (iter->get_type(&fieldType) == S_OK) { 269 | ProcessDepType(pGlobal, deps, fieldType); 270 | } 271 | } 272 | } 273 | } 274 | } 275 | 276 | // funcs 277 | { 278 | if (iter.Find(pUDT, SymTagFunction, NULL)) { 279 | while (iter.Next()) { 280 | 281 | #if defined (_DEBUG) 282 | Bstr name; 283 | iter->get_name(&name); 284 | #endif 285 | 286 | ComRef funcType; 287 | iter->get_type(&funcType); 288 | 289 | ComRef returnType; 290 | if (funcType->get_type(&returnType) == S_OK) { 291 | ProcessDepType(pGlobal, deps, returnType); 292 | } 293 | 294 | SymbolEnumerator arg; 295 | if (arg.Find(*funcType, SymTagNull, NULL)) { 296 | while (arg.Next()) { 297 | 298 | ComRef argType; 299 | if (arg->get_type(&argType) == S_OK) { 300 | ProcessDepType(pGlobal, deps, argType); 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | 308 | // remove self 309 | std::wstring key(*udtName); 310 | auto inode = deps.find(key); 311 | if (inode != deps.end()) 312 | { 313 | deps.erase(inode); 314 | } 315 | } 316 | 317 | // 318 | // GET GRAPH 319 | // 320 | 321 | static UdtGraphPtr GetUdtGraph(IDiaSymbol* global, const wchar_t* filter = NULL) 322 | { 323 | UdtGraphPtr result(std::make_shared()); 324 | 325 | SymbolEnumerator sym; 326 | if (sym.Find(global, SymTagUDT, filter)) { 327 | while (sym.Next()) { 328 | 329 | Bstr name; 330 | if (sym->get_name(&name) == S_OK) { 331 | 332 | std::wstring sname(*name); 333 | if (IsAllowedName(sname.c_str())) { 334 | 335 | if (!result->contains(sname)) { 336 | 337 | DWORD id; 338 | sym->get_symIndexId(&id); 339 | 340 | auto node = std::make_shared(); 341 | node->symbol = sym.ref(); 342 | node->id = id; 343 | node->name = sname; 344 | result->insert(node); 345 | 346 | GetUdtDeps(global, *sym, node->dep_s); 347 | } 348 | } 349 | } 350 | } 351 | } 352 | 353 | // map dep_s to dep_n 354 | for (auto& inode : result->nodes) { 355 | auto node = inode.second; 356 | 357 | for (auto& isym : node->dep_s) { 358 | 359 | if (node->dep_n.find(isym.first) == node->dep_n.end()) { 360 | 361 | auto idepN = result->nodes.find(isym.first); 362 | if (idepN != result->nodes.end()) 363 | { 364 | insert(node->dep_n, idepN->first, idepN->second); 365 | } 366 | } 367 | } 368 | } 369 | 370 | return result; 371 | } 372 | 373 | static void ExpandDeps(UdtNodePtr node, UdtGraphPtr input, UdtGraphPtr result) 374 | { 375 | std::vector deps; 376 | for (auto& idep : node->dep_n) { 377 | deps.push_back(idep.second); 378 | } 379 | 380 | for (;;) { 381 | if (deps.empty()) break; 382 | 383 | auto dep = deps.back(); 384 | deps.pop_back(); 385 | 386 | if (result->nodes.find(dep->name) == result->nodes.end()) { 387 | 388 | result->insert(dep->name, dep); 389 | 390 | for (auto& idep : dep->dep_n) { 391 | deps.push_back(idep.second); 392 | } 393 | } 394 | } 395 | } 396 | 397 | static UdtGraphPtr FilterUdtGraph(UdtGraphPtr input, const std::wstring& filter, BOOL bExpandDeps = FALSE) 398 | { 399 | UdtGraphPtr result(std::make_shared()); 400 | 401 | std::wstring filterx(filter); 402 | replaceAll(filterx, L"\"", L""); 403 | auto names = split(filterx, L";"); 404 | 405 | for (auto& name : names) 406 | { 407 | std::wstring namex(name); 408 | trim(namex); 409 | 410 | const bool exclude = startsWith(namex, L"-"); 411 | if (!exclude) { 412 | 413 | replace(namex, L"-", L""); 414 | trim(namex); 415 | 416 | auto inode = input->nodes.find(namex); 417 | if (inode != input->nodes.end() && inode->second) { 418 | 419 | auto node = inode->second; 420 | if (!result->contains(node->name)) { 421 | result->insert(node); 422 | } 423 | if (bExpandDeps) { 424 | ExpandDeps(node, input, result); 425 | } 426 | } 427 | } 428 | } 429 | 430 | // remove excluded nodes 431 | for (auto& name : names) 432 | { 433 | std::wstring namex(name); 434 | trim(namex); 435 | 436 | const bool exclude = startsWith(namex, L"-"); 437 | if (exclude) { 438 | 439 | replace(namex, L"-", L""); 440 | trim(namex); 441 | 442 | auto inode = result->nodes.find(namex); 443 | if (inode != result->nodes.end()) { 444 | result->nodes.erase(inode); 445 | } 446 | } 447 | } 448 | 449 | return result; 450 | } 451 | 452 | // 453 | // DEP RESOLVER 454 | // 455 | 456 | static bool Depends(const UdtNodePtr& a, const UdtNodePtr& b) 457 | { 458 | if (a->dep_s.find(b->name) != a->dep_s.end()) return true; 459 | 460 | std::vector deps; 461 | for (auto& idep : a->dep_n) { 462 | deps.push_back(idep.second); 463 | } 464 | 465 | std::unordered_set processed; 466 | 467 | for (;;) { 468 | if (deps.empty()) break; 469 | 470 | auto dep = deps.back(); 471 | deps.pop_back(); 472 | 473 | if (dep->dep_s.find(b->name) != dep->dep_s.end()) return true; 474 | 475 | processed.insert(dep->id); 476 | 477 | for (auto& idep : dep->dep_n) { 478 | if (processed.find(idep.second->id) == processed.end()) { 479 | deps.push_back(idep.second); 480 | } 481 | } 482 | } 483 | 484 | return false; 485 | } 486 | 487 | static ResolvedUdtGraphPtr ResolveDeps(UdtGraphPtr input) 488 | { 489 | ResolvedUdtGraphPtr result(std::make_shared()); 490 | 491 | std::list nodes; 492 | { 493 | std::vector nodeV; 494 | for (auto& iter : input->nodes) { 495 | nodeV.push_back(iter.second); 496 | } 497 | struct { 498 | inline bool operator()(const UdtNodePtr& a, const UdtNodePtr& b) const { 499 | return (a->dep_s.size() < b->dep_s.size()); 500 | } 501 | } comparator; 502 | std::sort(nodeV.begin(), nodeV.end(), comparator); 503 | 504 | for (auto& iter : nodeV) { 505 | nodes.push_back(iter); 506 | } 507 | } 508 | 509 | std::list resolved; 510 | while (!nodes.empty()) { 511 | 512 | resolved.clear(); 513 | for (auto& node : nodes) { 514 | 515 | bool haveDeps = false; 516 | 517 | for (auto& inner : nodes) { 518 | if (node != inner) { 519 | if (Depends(node, inner)) { 520 | haveDeps = true; 521 | break; 522 | } 523 | } 524 | } 525 | 526 | if (!haveDeps) { 527 | resolved.push_back(node); 528 | } 529 | } 530 | 531 | if (resolved.empty()) { 532 | UdtNodePtr bestNode; 533 | int minDeps = INT_MAX; 534 | for (auto& node : nodes) { 535 | if (minDeps > node->dep_s.size()) { 536 | minDeps = (int)node->dep_s.size(); 537 | bestNode = node; 538 | } 539 | } 540 | result->nodes.push_back(bestNode); 541 | nodes.remove(bestNode); 542 | } 543 | 544 | for (auto& node : resolved) { 545 | result->nodes.push_back(node); 546 | nodes.remove(node); 547 | } 548 | } 549 | 550 | #if defined(_DEBUG) 551 | for (auto& iter : result->nodes) { 552 | result->names.push_back(iter->name); 553 | } 554 | #endif 555 | 556 | return result; 557 | } 558 | 559 | static ResolvedUdtGraphPtr SortBySymId(UdtGraphPtr input) 560 | { 561 | ResolvedUdtGraphPtr result(std::make_shared()); 562 | 563 | for (auto& iter : input->nodes) { 564 | result->nodes.push_back(iter.second); 565 | } 566 | 567 | struct { 568 | inline bool operator()(const UdtNodePtr& a, const UdtNodePtr& b) const { 569 | return (a->id < b->id); 570 | } 571 | } comparator; 572 | 573 | std::sort(result->nodes.begin(), result->nodes.end(), comparator); 574 | 575 | #if defined(_DEBUG) 576 | for (auto& iter : result->nodes) { 577 | result->names.push_back(iter->name); 578 | } 579 | #endif 580 | 581 | return result; 582 | } 583 | --------------------------------------------------------------------------------