1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 // Create an IDiaData source and open a PDB file.
11 static bool LoadDataFromPdb(const wchar_t* filename
,
12 IDiaDataSource
** source
,
13 IDiaSession
** session
,
15 DWORD
* machine_type
) {
16 // Alternate path to search for debug data.
17 const wchar_t search_path
[] = L
"SRV**\\\\symbols\\symbols";
19 HRESULT hr
= CoInitialize(NULL
);
21 // Obtain access to the provider.
22 hr
= CoCreateInstance(__uuidof(DiaSource
),
25 __uuidof(IDiaDataSource
),
29 printf("CoCreateInstance failed - HRESULT = %08lX\n", hr
);
33 wchar_t ext
[MAX_PATH
];
34 _wsplitpath_s(filename
, NULL
, 0, NULL
, 0, NULL
, 0, ext
, MAX_PATH
);
36 // Open and prepare the debug data associated with the executable.
37 hr
= (*source
)->loadDataForExe(filename
, search_path
, NULL
);
39 printf("loadDataForExe failed - HRESULT = %08lX\n", hr
);
43 // Open a session for querying symbols.
44 hr
= (*source
)->openSession(session
);
47 printf("openSession failed - HRESULT = %08lX\n", hr
);
51 // Retrieve a reference to the global scope.
52 hr
= (*session
)->get_globalScope(global
);
55 printf("get_globalScope failed\n");
59 // Set machine type for getting correct register names.
60 if (SUCCEEDED((*global
)->get_machineType(&mach_type
))) {
62 case IMAGE_FILE_MACHINE_I386
:
63 *machine_type
= CV_CFL_80386
;
65 case IMAGE_FILE_MACHINE_IA64
:
66 *machine_type
= CV_CFL_IA64
;
68 case IMAGE_FILE_MACHINE_AMD64
:
69 *machine_type
= CV_CFL_AMD64
;
72 printf("unexpected machine type\n");
80 // Release DIA objects and CoUninitialize.
81 static void Cleanup(IDiaSymbol
* global_symbol
, IDiaSession
* dia_session
) {
83 global_symbol
->Release();
85 dia_session
->Release();
89 static void PrintIfDynamicInitializer(const std::wstring
& module
,
93 if (FAILED(symbol
->get_symTag(&symtag
)))
96 if (symtag
!= SymTagFunction
&& symtag
!= SymTagBlock
)
100 if (SUCCEEDED(symbol
->get_name(&bstr_name
))) {
101 if (wcsstr(bstr_name
, L
"`dynamic initializer for '")) {
102 wprintf(L
"%s: %s\n", module
.c_str(), bstr_name
);
103 SysFreeString(bstr_name
);
108 static bool DumpStaticInitializers(IDiaSymbol
* global_symbol
) {
109 // Retrieve the compilands first.
110 IDiaEnumSymbols
* enum_symbols
;
111 if (FAILED(global_symbol
->findChildren(
112 SymTagCompiland
, NULL
, nsNone
, &enum_symbols
))) {
116 IDiaSymbol
* compiland
;
117 ULONG element_count
= 0;
119 std::wstring current_module
;
120 while (SUCCEEDED(enum_symbols
->Next(1, &compiland
, &element_count
)) &&
121 (element_count
== 1)) {
123 if (FAILED(compiland
->get_name(&bstr_name
))) {
124 current_module
= L
"<unknown>";
126 current_module
= bstr_name
;
127 SysFreeString(bstr_name
);
130 // Find all the symbols defined in this compiland, and print them if they
131 // have the name corresponding to an initializer.
132 IDiaEnumSymbols
* enum_children
;
133 if (SUCCEEDED(compiland
->findChildren(
134 SymTagNull
, NULL
, nsNone
, &enum_children
))) {
137 while (SUCCEEDED(enum_children
->Next(1, &symbol
, &children
)) &&
138 children
== 1) { // Enumerate until we don't get any more symbols.
139 PrintIfDynamicInitializer(current_module
, symbol
);
142 enum_children
->Release();
144 compiland
->Release();
147 enum_symbols
->Release();
151 int wmain(int argc
, wchar_t* argv
[]) {
153 wprintf(L
"usage: %ls binary_name\n", argv
[0]);
157 IDiaDataSource
* dia_data_source
;
158 IDiaSession
* dia_session
;
159 IDiaSymbol
* global_symbol
;
160 DWORD machine_type
= CV_CFL_80386
;
161 if (!LoadDataFromPdb(argv
[1],
166 wprintf(L
"Couldn't load data from pdb.\n");
170 wprintf(L
"Static initializers in %s:\n", argv
[1]);
172 if (!DumpStaticInitializers(global_symbol
))
175 Cleanup(global_symbol
, dia_session
);