Make Chromoting browser tests pass again
[chromium-blink-merge.git] / tools / win / static_initializers / static_initializers.cc
blob440bb9de8339cf4d166d2fcc358954c68e101d04
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.
5 #include <dia2.h>
6 #include <stdio.h>
8 #include <string>
10 // Create an IDiaData source and open a PDB file.
11 static bool LoadDataFromPdb(const wchar_t* filename,
12 IDiaDataSource** source,
13 IDiaSession** session,
14 IDiaSymbol** global,
15 DWORD* machine_type) {
16 // Alternate path to search for debug data.
17 const wchar_t search_path[] = L"SRV**\\\\symbols\\symbols";
18 DWORD mach_type = 0;
19 HRESULT hr = CoInitialize(NULL);
21 // Obtain access to the provider.
22 hr = CoCreateInstance(__uuidof(DiaSource),
23 NULL,
24 CLSCTX_INPROC_SERVER,
25 __uuidof(IDiaDataSource),
26 (void**)source);
28 if (FAILED(hr)) {
29 printf("CoCreateInstance failed - HRESULT = %08lX\n", hr);
30 return false;
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);
38 if (FAILED(hr)) {
39 printf("loadDataForExe failed - HRESULT = %08lX\n", hr);
40 return false;
43 // Open a session for querying symbols.
44 hr = (*source)->openSession(session);
46 if (FAILED(hr)) {
47 printf("openSession failed - HRESULT = %08lX\n", hr);
48 return false;
51 // Retrieve a reference to the global scope.
52 hr = (*session)->get_globalScope(global);
54 if (FAILED(hr)) {
55 printf("get_globalScope failed\n");
56 return false;
59 // Set machine type for getting correct register names.
60 if (SUCCEEDED((*global)->get_machineType(&mach_type))) {
61 switch (mach_type) {
62 case IMAGE_FILE_MACHINE_I386:
63 *machine_type = CV_CFL_80386;
64 break;
65 case IMAGE_FILE_MACHINE_IA64:
66 *machine_type = CV_CFL_IA64;
67 break;
68 case IMAGE_FILE_MACHINE_AMD64:
69 *machine_type = CV_CFL_AMD64;
70 break;
71 default:
72 printf("unexpected machine type\n");
73 return false;
77 return true;
80 // Release DIA objects and CoUninitialize.
81 static void Cleanup(IDiaSymbol* global_symbol, IDiaSession* dia_session) {
82 if (global_symbol)
83 global_symbol->Release();
84 if (dia_session)
85 dia_session->Release();
86 CoUninitialize();
89 static void PrintIfDynamicInitializer(const std::wstring& module,
90 IDiaSymbol* symbol) {
91 DWORD symtag;
93 if (FAILED(symbol->get_symTag(&symtag)))
94 return;
96 if (symtag != SymTagFunction && symtag != SymTagBlock)
97 return;
99 BSTR bstr_name;
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))) {
113 return false;
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)) {
122 BSTR bstr_name;
123 if (FAILED(compiland->get_name(&bstr_name))) {
124 current_module = L"<unknown>";
125 } else {
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))) {
135 IDiaSymbol* symbol;
136 ULONG children = 0;
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);
140 symbol->Release();
142 enum_children->Release();
144 compiland->Release();
147 enum_symbols->Release();
148 return true;
151 int wmain(int argc, wchar_t* argv[]) {
152 if (argc != 2) {
153 wprintf(L"usage: %ls binary_name\n", argv[0]);
154 return 1;
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],
162 &dia_data_source,
163 &dia_session,
164 &global_symbol,
165 &machine_type)) {
166 wprintf(L"Couldn't load data from pdb.\n");
167 return 1;
170 wprintf(L"Static initializers in %s:\n", argv[1]);
172 if (!DumpStaticInitializers(global_symbol))
173 return 1;
175 Cleanup(global_symbol, dia_session);
177 return 0;