| Index: tools/win/static_initializers/static_initializers.cc
|
| diff --git a/tools/win/static_initializers/static_initializers.cc b/tools/win/static_initializers/static_initializers.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a09715ee47263a71aa846cb79117b4cfcb3c2c21
|
| --- /dev/null
|
| +++ b/tools/win/static_initializers/static_initializers.cc
|
| @@ -0,0 +1,178 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include <dia2.h>
|
| +#include <stdio.h>
|
| +
|
| +#include <string>
|
| +
|
| +// Create an IDiaData source and open a PDB file.
|
| +static bool LoadDataFromPdb(const wchar_t* filename,
|
| + IDiaDataSource** source,
|
| + IDiaSession** session,
|
| + IDiaSymbol** global,
|
| + DWORD* machine_type) {
|
| + // Alternate path to search for debug data.
|
| + const wchar_t search_path[] = L"SRV**\\\\symbols\\symbols";
|
| + DWORD mach_type = 0;
|
| + HRESULT hr = CoInitialize(NULL);
|
| +
|
| + // Obtain access to the provider.
|
| + hr = CoCreateInstance(__uuidof(DiaSource),
|
| + NULL,
|
| + CLSCTX_INPROC_SERVER,
|
| + __uuidof(IDiaDataSource),
|
| + (void**)source);
|
| +
|
| + if (FAILED(hr)) {
|
| + printf("CoCreateInstance failed - HRESULT = %08X\n", hr);
|
| + return false;
|
| + }
|
| +
|
| + wchar_t ext[MAX_PATH];
|
| + _wsplitpath_s(filename, NULL, 0, NULL, 0, NULL, 0, ext, MAX_PATH);
|
| +
|
| + // Open and prepare the debug data associated with the executable.
|
| + hr = (*source)->loadDataForExe(filename, search_path, NULL);
|
| + if (FAILED(hr)) {
|
| + printf("loadDataForExe failed - HRESULT = %08X\n", hr);
|
| + return false;
|
| + }
|
| +
|
| + // Open a session for querying symbols.
|
| + hr = (*source)->openSession(session);
|
| +
|
| + if (FAILED(hr)) {
|
| + printf("openSession failed - HRESULT = %08X\n", hr);
|
| + return false;
|
| + }
|
| +
|
| + // Retrieve a reference to the global scope.
|
| + hr = (*session)->get_globalScope(global);
|
| +
|
| + if (FAILED(hr)) {
|
| + printf("get_globalScope failed\n");
|
| + return false;
|
| + }
|
| +
|
| + // Set machine type for getting correct register names.
|
| + if (SUCCEEDED((*global)->get_machineType(&mach_type))) {
|
| + switch (mach_type) {
|
| + case IMAGE_FILE_MACHINE_I386:
|
| + *machine_type = CV_CFL_80386;
|
| + break;
|
| + case IMAGE_FILE_MACHINE_IA64:
|
| + *machine_type = CV_CFL_IA64;
|
| + break;
|
| + case IMAGE_FILE_MACHINE_AMD64:
|
| + *machine_type = CV_CFL_AMD64;
|
| + break;
|
| + default:
|
| + printf("unexpected machine type\n");
|
| + return false;
|
| + }
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +// Release DIA objects and CoUninitialize.
|
| +static void Cleanup(IDiaSymbol* global_symbol, IDiaSession* dia_session) {
|
| + if (global_symbol)
|
| + global_symbol->Release();
|
| + if (dia_session)
|
| + dia_session->Release();
|
| + CoUninitialize();
|
| +}
|
| +
|
| +static void PrintIfDynamicInitializer(const std::wstring& module,
|
| + IDiaSymbol* symbol) {
|
| + DWORD symtag;
|
| +
|
| + if (FAILED(symbol->get_symTag(&symtag)))
|
| + return;
|
| +
|
| + if (symtag != SymTagFunction && symtag != SymTagBlock)
|
| + return;
|
| +
|
| + BSTR bstr_name;
|
| + if (SUCCEEDED(symbol->get_name(&bstr_name))) {
|
| + if (wcsstr(bstr_name, L"`dynamic initializer for '")) {
|
| + wprintf(L"%s: %s\n", module.c_str(), bstr_name);
|
| + SysFreeString(bstr_name);
|
| + }
|
| + }
|
| +}
|
| +
|
| +static bool DumpStaticInitializers(IDiaSymbol* global_symbol) {
|
| + // Retrieve the compilands first.
|
| + IDiaEnumSymbols* enum_symbols;
|
| + if (FAILED(global_symbol->findChildren(
|
| + SymTagCompiland, NULL, nsNone, &enum_symbols))) {
|
| + return false;
|
| + }
|
| +
|
| + IDiaSymbol* compiland;
|
| + ULONG element_count = 0;
|
| +
|
| + std::wstring current_module;
|
| + while (SUCCEEDED(enum_symbols->Next(1, &compiland, &element_count)) &&
|
| + (element_count == 1)) {
|
| + BSTR bstr_name;
|
| + if (FAILED(compiland->get_name(&bstr_name))) {
|
| + current_module = L"<unknown>";
|
| + } else {
|
| + current_module = bstr_name;
|
| + SysFreeString(bstr_name);
|
| + }
|
| +
|
| + // Find all the symbols defined in this compiland, and print them if they
|
| + // have the name corresponding to an initializer.
|
| + IDiaEnumSymbols* enum_children;
|
| + if (SUCCEEDED(compiland->findChildren(
|
| + SymTagNull, NULL, nsNone, &enum_children))) {
|
| + IDiaSymbol* symbol;
|
| + ULONG children = 0;
|
| + while (SUCCEEDED(enum_children->Next(1, &symbol, &children)) &&
|
| + children == 1) { // Enumerate until we don't get any more symbols.
|
| + PrintIfDynamicInitializer(current_module, symbol);
|
| + symbol->Release();
|
| + }
|
| + enum_children->Release();
|
| + }
|
| + compiland->Release();
|
| + }
|
| +
|
| + enum_symbols->Release();
|
| + return true;
|
| +}
|
| +
|
| +int wmain(int argc, wchar_t* argv[]) {
|
| + if (argc != 2) {
|
| + wprintf(L"usage: %ls binary_name\n", argv[0]);
|
| + return 1;
|
| + }
|
| +
|
| + IDiaDataSource* dia_data_source;
|
| + IDiaSession* dia_session;
|
| + IDiaSymbol* global_symbol;
|
| + DWORD machine_type = CV_CFL_80386;
|
| + if (!LoadDataFromPdb(argv[1],
|
| + &dia_data_source,
|
| + &dia_session,
|
| + &global_symbol,
|
| + &machine_type)) {
|
| + wprintf(L"Couldn't load data from pdb.\n");
|
| + return 1;
|
| + }
|
| +
|
| + wprintf(L"Static initializers in %s:\n", argv[1]);
|
| +
|
| + if (!DumpStaticInitializers(global_symbol))
|
| + return 1;
|
| +
|
| + Cleanup(global_symbol, dia_session);
|
| +
|
| + return 0;
|
| +}
|
|
|