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);