Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / win / static_initializers / static_initializers.cc
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.
4
5 #include <dia2.h>
6 #include <stdio.h>
7
8 #include <string>
9
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);
20
21   // Obtain access to the provider.
22   hr = CoCreateInstance(__uuidof(DiaSource),
23                         NULL,
24                         CLSCTX_INPROC_SERVER,
25                         __uuidof(IDiaDataSource),
26                         (void**)source);
27
28   if (FAILED(hr)) {
29     printf("CoCreateInstance failed - HRESULT = %08lX\n", hr);
30     return false;
31   }
32
33   wchar_t ext[MAX_PATH];
34   _wsplitpath_s(filename, NULL, 0, NULL, 0, NULL, 0, ext, MAX_PATH);
35
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;
41   }
42
43   // Open a session for querying symbols.
44   hr = (*source)->openSession(session);
45
46   if (FAILED(hr)) {
47     printf("openSession failed - HRESULT = %08lX\n", hr);
48     return false;
49   }
50
51   // Retrieve a reference to the global scope.
52   hr = (*session)->get_globalScope(global);
53
54   if (FAILED(hr)) {
55     printf("get_globalScope failed\n");
56     return false;
57   }
58
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;
74     }
75   }
76
77   return true;
78 }
79
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();
87 }
88
89 static void PrintIfDynamicInitializer(const std::wstring& module,
90                                       IDiaSymbol* symbol) {
91   DWORD symtag;
92
93   if (FAILED(symbol->get_symTag(&symtag)))
94     return;
95
96   if (symtag != SymTagFunction && symtag != SymTagBlock)
97     return;
98
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);
104     }
105   }
106 }
107
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;
114   }
115
116   IDiaSymbol* compiland;
117   ULONG element_count = 0;
118
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);
128     }
129
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();
141       }
142       enum_children->Release();
143     }
144     compiland->Release();
145   }
146
147   enum_symbols->Release();
148   return true;
149 }
150
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;
155   }
156
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;
168   }
169
170   wprintf(L"Static initializers in %s:\n", argv[1]);
171
172   if (!DumpStaticInitializers(global_symbol))
173     return 1;
174
175   Cleanup(global_symbol, dia_session);
176
177   return 0;
178 }