150e299b00e803f085b34847dfe5232b471d84197mmentovai// Copyright (c) 2007, Google Inc. 250e299b00e803f085b34847dfe5232b471d84197mmentovai// All rights reserved. 350e299b00e803f085b34847dfe5232b471d84197mmentovai// 450e299b00e803f085b34847dfe5232b471d84197mmentovai// Redistribution and use in source and binary forms, with or without 550e299b00e803f085b34847dfe5232b471d84197mmentovai// modification, are permitted provided that the following conditions are 650e299b00e803f085b34847dfe5232b471d84197mmentovai// met: 750e299b00e803f085b34847dfe5232b471d84197mmentovai// 850e299b00e803f085b34847dfe5232b471d84197mmentovai// * Redistributions of source code must retain the above copyright 950e299b00e803f085b34847dfe5232b471d84197mmentovai// notice, this list of conditions and the following disclaimer. 1050e299b00e803f085b34847dfe5232b471d84197mmentovai// * Redistributions in binary form must reproduce the above 1150e299b00e803f085b34847dfe5232b471d84197mmentovai// copyright notice, this list of conditions and the following disclaimer 1250e299b00e803f085b34847dfe5232b471d84197mmentovai// in the documentation and/or other materials provided with the 1350e299b00e803f085b34847dfe5232b471d84197mmentovai// distribution. 1450e299b00e803f085b34847dfe5232b471d84197mmentovai// * Neither the name of Google Inc. nor the names of its 1550e299b00e803f085b34847dfe5232b471d84197mmentovai// contributors may be used to endorse or promote products derived from 1650e299b00e803f085b34847dfe5232b471d84197mmentovai// this software without specific prior written permission. 1750e299b00e803f085b34847dfe5232b471d84197mmentovai// 1850e299b00e803f085b34847dfe5232b471d84197mmentovai// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1950e299b00e803f085b34847dfe5232b471d84197mmentovai// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2050e299b00e803f085b34847dfe5232b471d84197mmentovai// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2150e299b00e803f085b34847dfe5232b471d84197mmentovai// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2250e299b00e803f085b34847dfe5232b471d84197mmentovai// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2350e299b00e803f085b34847dfe5232b471d84197mmentovai// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2450e299b00e803f085b34847dfe5232b471d84197mmentovai// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2550e299b00e803f085b34847dfe5232b471d84197mmentovai// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2650e299b00e803f085b34847dfe5232b471d84197mmentovai// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2750e299b00e803f085b34847dfe5232b471d84197mmentovai// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2850e299b00e803f085b34847dfe5232b471d84197mmentovai// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2950e299b00e803f085b34847dfe5232b471d84197mmentovai 3050e299b00e803f085b34847dfe5232b471d84197mmentovai// ms_symbol_server_converter.cc: Obtain symbol files from a Microsoft 31e5dc60822e5938fea2ae892ccddb906641ba174emmentovai// symbol server, and convert them to Breakpad's dumped format. 3250e299b00e803f085b34847dfe5232b471d84197mmentovai// 3350e299b00e803f085b34847dfe5232b471d84197mmentovai// See ms_symbol_server_converter.h for documentation. 3450e299b00e803f085b34847dfe5232b471d84197mmentovai// 3550e299b00e803f085b34847dfe5232b471d84197mmentovai// Author: Mark Mentovai 3650e299b00e803f085b34847dfe5232b471d84197mmentovai 37de9fe36b16a45972571b9d650633fe5cb156b536ted.mielczarek@gmail.com#include <windows.h> 38de9fe36b16a45972571b9d650633fe5cb156b536ted.mielczarek@gmail.com#include <dbghelp.h> 3950e299b00e803f085b34847dfe5232b471d84197mmentovai 4050e299b00e803f085b34847dfe5232b471d84197mmentovai#include <cassert> 4150e299b00e803f085b34847dfe5232b471d84197mmentovai#include <cstdio> 4250e299b00e803f085b34847dfe5232b471d84197mmentovai 4350e299b00e803f085b34847dfe5232b471d84197mmentovai#include "tools/windows/converter/ms_symbol_server_converter.h" 4450e299b00e803f085b34847dfe5232b471d84197mmentovai#include "common/windows/pdb_source_line_writer.h" 4550e299b00e803f085b34847dfe5232b471d84197mmentovai#include "common/windows/string_utils-inl.h" 4650e299b00e803f085b34847dfe5232b471d84197mmentovai 4750e299b00e803f085b34847dfe5232b471d84197mmentovai// SYMOPT_NO_PROMPTS is not defined in earlier platform SDKs. Define it 4850e299b00e803f085b34847dfe5232b471d84197mmentovai// in that case, in the event that this code is used with a newer version 4950e299b00e803f085b34847dfe5232b471d84197mmentovai// of DbgHelp at runtime that recognizes the option. The presence of this 5050e299b00e803f085b34847dfe5232b471d84197mmentovai// bit in the symbol options should not harm earlier versions of DbgHelp. 5150e299b00e803f085b34847dfe5232b471d84197mmentovai#ifndef SYMOPT_NO_PROMPTS 5250e299b00e803f085b34847dfe5232b471d84197mmentovai#define SYMOPT_NO_PROMPTS 0x00080000 5350e299b00e803f085b34847dfe5232b471d84197mmentovai#endif // SYMOPT_NO_PROMPTS 5450e299b00e803f085b34847dfe5232b471d84197mmentovai 55e5dc60822e5938fea2ae892ccddb906641ba174emmentovainamespace google_breakpad { 5650e299b00e803f085b34847dfe5232b471d84197mmentovai 5750e299b00e803f085b34847dfe5232b471d84197mmentovai// Use sscanf_s if it is available, to quench the warning about scanf being 5850e299b00e803f085b34847dfe5232b471d84197mmentovai// deprecated. Use scanf where sscanf_is not available. Note that the 5950e299b00e803f085b34847dfe5232b471d84197mmentovai// parameters passed to sscanf and sscanf_s are only compatible as long as 6050e299b00e803f085b34847dfe5232b471d84197mmentovai// fields of type c, C, s, S, and [ are not used. 6150e299b00e803f085b34847dfe5232b471d84197mmentovai#if _MSC_VER >= 1400 // MSVC 2005/8 6250e299b00e803f085b34847dfe5232b471d84197mmentovai#define SSCANF sscanf_s 6350e299b00e803f085b34847dfe5232b471d84197mmentovai#else // _MSC_VER >= 1400 6450e299b00e803f085b34847dfe5232b471d84197mmentovai#define SSCANF sscanf 6550e299b00e803f085b34847dfe5232b471d84197mmentovai#endif // _MSC_VER >= 1400 6650e299b00e803f085b34847dfe5232b471d84197mmentovai 6750e299b00e803f085b34847dfe5232b471d84197mmentovaibool GUIDOrSignatureIdentifier::InitializeFromString( 6850e299b00e803f085b34847dfe5232b471d84197mmentovai const string &identifier) { 6950e299b00e803f085b34847dfe5232b471d84197mmentovai type_ = TYPE_NONE; 7050e299b00e803f085b34847dfe5232b471d84197mmentovai 7150e299b00e803f085b34847dfe5232b471d84197mmentovai size_t length = identifier.length(); 7250e299b00e803f085b34847dfe5232b471d84197mmentovai 7350e299b00e803f085b34847dfe5232b471d84197mmentovai if (length > 32 && length <= 40) { 7450e299b00e803f085b34847dfe5232b471d84197mmentovai // GUID 7550e299b00e803f085b34847dfe5232b471d84197mmentovai if (SSCANF(identifier.c_str(), 7650e299b00e803f085b34847dfe5232b471d84197mmentovai "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%X", 7750e299b00e803f085b34847dfe5232b471d84197mmentovai &guid_.Data1, &guid_.Data2, &guid_.Data3, 7850e299b00e803f085b34847dfe5232b471d84197mmentovai &guid_.Data4[0], &guid_.Data4[1], 7950e299b00e803f085b34847dfe5232b471d84197mmentovai &guid_.Data4[2], &guid_.Data4[3], 8050e299b00e803f085b34847dfe5232b471d84197mmentovai &guid_.Data4[4], &guid_.Data4[5], 8150e299b00e803f085b34847dfe5232b471d84197mmentovai &guid_.Data4[6], &guid_.Data4[7], 8250e299b00e803f085b34847dfe5232b471d84197mmentovai &age_) != 12) { 8350e299b00e803f085b34847dfe5232b471d84197mmentovai return false; 8450e299b00e803f085b34847dfe5232b471d84197mmentovai } 8550e299b00e803f085b34847dfe5232b471d84197mmentovai 8650e299b00e803f085b34847dfe5232b471d84197mmentovai type_ = TYPE_GUID; 8750e299b00e803f085b34847dfe5232b471d84197mmentovai } else if (length > 8 && length <= 15) { 8850e299b00e803f085b34847dfe5232b471d84197mmentovai // Signature 8950e299b00e803f085b34847dfe5232b471d84197mmentovai if (SSCANF(identifier.c_str(), "%08X%x", &signature_, &age_) != 2) { 9050e299b00e803f085b34847dfe5232b471d84197mmentovai return false; 9150e299b00e803f085b34847dfe5232b471d84197mmentovai } 9250e299b00e803f085b34847dfe5232b471d84197mmentovai 9350e299b00e803f085b34847dfe5232b471d84197mmentovai type_ = TYPE_SIGNATURE; 9450e299b00e803f085b34847dfe5232b471d84197mmentovai } else { 9550e299b00e803f085b34847dfe5232b471d84197mmentovai return false; 9650e299b00e803f085b34847dfe5232b471d84197mmentovai } 9750e299b00e803f085b34847dfe5232b471d84197mmentovai 9850e299b00e803f085b34847dfe5232b471d84197mmentovai return true; 9950e299b00e803f085b34847dfe5232b471d84197mmentovai} 10050e299b00e803f085b34847dfe5232b471d84197mmentovai 10150e299b00e803f085b34847dfe5232b471d84197mmentovai#undef SSCANF 10250e299b00e803f085b34847dfe5232b471d84197mmentovai 10350e299b00e803f085b34847dfe5232b471d84197mmentovaiMSSymbolServerConverter::MSSymbolServerConverter( 10450e299b00e803f085b34847dfe5232b471d84197mmentovai const string &local_cache, const vector<string> &symbol_servers) 10550e299b00e803f085b34847dfe5232b471d84197mmentovai : symbol_path_(), 10650e299b00e803f085b34847dfe5232b471d84197mmentovai fail_dns_(false), 10750e299b00e803f085b34847dfe5232b471d84197mmentovai fail_timeout_(false), 10850e299b00e803f085b34847dfe5232b471d84197mmentovai fail_not_found_(false) { 10950e299b00e803f085b34847dfe5232b471d84197mmentovai // Setting local_cache can be done without verifying that it exists because 11050e299b00e803f085b34847dfe5232b471d84197mmentovai // SymSrv will create it if it is missing - any creation failures will occur 11150e299b00e803f085b34847dfe5232b471d84197mmentovai // at that time, so there's nothing to check here, making it safe to 11250e299b00e803f085b34847dfe5232b471d84197mmentovai // assign this in the constructor. 11350e299b00e803f085b34847dfe5232b471d84197mmentovai 11450e299b00e803f085b34847dfe5232b471d84197mmentovai assert(symbol_servers.size() > 0); 11550e299b00e803f085b34847dfe5232b471d84197mmentovai 1160a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com#if !defined(NDEBUG) 11750e299b00e803f085b34847dfe5232b471d84197mmentovai // These are characters that are interpreted as having special meanings in 11850e299b00e803f085b34847dfe5232b471d84197mmentovai // symbol_path_. 1190a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com const char kInvalidCharacters[] = "*;"; 12050e299b00e803f085b34847dfe5232b471d84197mmentovai assert(local_cache.find_first_of(kInvalidCharacters) == string::npos); 1210a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com#endif // !defined(NDEBUG) 12250e299b00e803f085b34847dfe5232b471d84197mmentovai 12350e299b00e803f085b34847dfe5232b471d84197mmentovai for (vector<string>::const_iterator symbol_server = symbol_servers.begin(); 12450e299b00e803f085b34847dfe5232b471d84197mmentovai symbol_server != symbol_servers.end(); 12550e299b00e803f085b34847dfe5232b471d84197mmentovai ++symbol_server) { 12650e299b00e803f085b34847dfe5232b471d84197mmentovai // The symbol path format is explained by 12750e299b00e803f085b34847dfe5232b471d84197mmentovai // http://msdn.microsoft.com/library/en-us/debug/base/using_symsrv.asp . 12850e299b00e803f085b34847dfe5232b471d84197mmentovai // "srv*" is the same as "symsrv*symsrv.dll*", which means that 12950e299b00e803f085b34847dfe5232b471d84197mmentovai // symsrv.dll is to be responsible for locating symbols. symsrv.dll 13050e299b00e803f085b34847dfe5232b471d84197mmentovai // interprets the rest of the string as a series of symbol stores separated 13150e299b00e803f085b34847dfe5232b471d84197mmentovai // by '*'. "srv*local_cache*symbol_server" means to check local_cache 13250e299b00e803f085b34847dfe5232b471d84197mmentovai // first for the symbol file, and if it is not found there, to check 13350e299b00e803f085b34847dfe5232b471d84197mmentovai // symbol_server. Symbol files found on the symbol server will be placed 13450e299b00e803f085b34847dfe5232b471d84197mmentovai // in the local cache, decompressed. 13550e299b00e803f085b34847dfe5232b471d84197mmentovai // 13650e299b00e803f085b34847dfe5232b471d84197mmentovai // Multiple specifications in this format may be presented, separated by 13750e299b00e803f085b34847dfe5232b471d84197mmentovai // semicolons. 13850e299b00e803f085b34847dfe5232b471d84197mmentovai 13950e299b00e803f085b34847dfe5232b471d84197mmentovai assert((*symbol_server).find_first_of(kInvalidCharacters) == string::npos); 14050e299b00e803f085b34847dfe5232b471d84197mmentovai symbol_path_ += "srv*" + local_cache + "*" + *symbol_server + ";"; 14150e299b00e803f085b34847dfe5232b471d84197mmentovai } 14250e299b00e803f085b34847dfe5232b471d84197mmentovai 14350e299b00e803f085b34847dfe5232b471d84197mmentovai // Strip the trailing semicolon. 14450e299b00e803f085b34847dfe5232b471d84197mmentovai symbol_path_.erase(symbol_path_.length() - 1); 14550e299b00e803f085b34847dfe5232b471d84197mmentovai} 14650e299b00e803f085b34847dfe5232b471d84197mmentovai 14750e299b00e803f085b34847dfe5232b471d84197mmentovai// A stack-based class that manages SymInitialize and SymCleanup calls. 14850e299b00e803f085b34847dfe5232b471d84197mmentovaiclass AutoSymSrv { 14950e299b00e803f085b34847dfe5232b471d84197mmentovai public: 15050e299b00e803f085b34847dfe5232b471d84197mmentovai AutoSymSrv() : initialized_(false) {} 15150e299b00e803f085b34847dfe5232b471d84197mmentovai 15250e299b00e803f085b34847dfe5232b471d84197mmentovai ~AutoSymSrv() { 15350e299b00e803f085b34847dfe5232b471d84197mmentovai if (!Cleanup()) { 15450e299b00e803f085b34847dfe5232b471d84197mmentovai // Print the error message here, because destructors have no return 15550e299b00e803f085b34847dfe5232b471d84197mmentovai // value. 15650e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, "~AutoSymSrv: SymCleanup: error %d\n", GetLastError()); 15750e299b00e803f085b34847dfe5232b471d84197mmentovai } 15850e299b00e803f085b34847dfe5232b471d84197mmentovai } 15950e299b00e803f085b34847dfe5232b471d84197mmentovai 16050e299b00e803f085b34847dfe5232b471d84197mmentovai bool Initialize(HANDLE process, char *path, bool invade_process) { 16150e299b00e803f085b34847dfe5232b471d84197mmentovai process_ = process; 16250e299b00e803f085b34847dfe5232b471d84197mmentovai initialized_ = SymInitialize(process, path, invade_process) == TRUE; 16350e299b00e803f085b34847dfe5232b471d84197mmentovai return initialized_; 16450e299b00e803f085b34847dfe5232b471d84197mmentovai } 16550e299b00e803f085b34847dfe5232b471d84197mmentovai 16650e299b00e803f085b34847dfe5232b471d84197mmentovai bool Cleanup() { 16750e299b00e803f085b34847dfe5232b471d84197mmentovai if (initialized_) { 16850e299b00e803f085b34847dfe5232b471d84197mmentovai if (SymCleanup(process_)) { 16950e299b00e803f085b34847dfe5232b471d84197mmentovai initialized_ = false; 17050e299b00e803f085b34847dfe5232b471d84197mmentovai return true; 17150e299b00e803f085b34847dfe5232b471d84197mmentovai } 17250e299b00e803f085b34847dfe5232b471d84197mmentovai return false; 17350e299b00e803f085b34847dfe5232b471d84197mmentovai } 17450e299b00e803f085b34847dfe5232b471d84197mmentovai 17550e299b00e803f085b34847dfe5232b471d84197mmentovai return true; 17650e299b00e803f085b34847dfe5232b471d84197mmentovai } 17750e299b00e803f085b34847dfe5232b471d84197mmentovai 17850e299b00e803f085b34847dfe5232b471d84197mmentovai private: 17950e299b00e803f085b34847dfe5232b471d84197mmentovai HANDLE process_; 18050e299b00e803f085b34847dfe5232b471d84197mmentovai bool initialized_; 18150e299b00e803f085b34847dfe5232b471d84197mmentovai}; 18250e299b00e803f085b34847dfe5232b471d84197mmentovai 18350e299b00e803f085b34847dfe5232b471d84197mmentovai// A stack-based class that "owns" a pathname and deletes it when destroyed, 18450e299b00e803f085b34847dfe5232b471d84197mmentovai// unless told not to by having its Release() method called. Early deletions 18550e299b00e803f085b34847dfe5232b471d84197mmentovai// are supported by calling Delete(). 18650e299b00e803f085b34847dfe5232b471d84197mmentovaiclass AutoDeleter { 18750e299b00e803f085b34847dfe5232b471d84197mmentovai public: 1880a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com explicit AutoDeleter(const string &path) : path_(path) {} 18950e299b00e803f085b34847dfe5232b471d84197mmentovai 19050e299b00e803f085b34847dfe5232b471d84197mmentovai ~AutoDeleter() { 19150e299b00e803f085b34847dfe5232b471d84197mmentovai int error; 19250e299b00e803f085b34847dfe5232b471d84197mmentovai if ((error = Delete()) != 0) { 19350e299b00e803f085b34847dfe5232b471d84197mmentovai // Print the error message here, because destructors have no return 19450e299b00e803f085b34847dfe5232b471d84197mmentovai // value. 19550e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, "~AutoDeleter: Delete: error %d for %s\n", 19650e299b00e803f085b34847dfe5232b471d84197mmentovai error, path_.c_str()); 19750e299b00e803f085b34847dfe5232b471d84197mmentovai } 19850e299b00e803f085b34847dfe5232b471d84197mmentovai } 19950e299b00e803f085b34847dfe5232b471d84197mmentovai 20050e299b00e803f085b34847dfe5232b471d84197mmentovai int Delete() { 20150e299b00e803f085b34847dfe5232b471d84197mmentovai if (path_.empty()) 20250e299b00e803f085b34847dfe5232b471d84197mmentovai return 0; 20350e299b00e803f085b34847dfe5232b471d84197mmentovai 20450e299b00e803f085b34847dfe5232b471d84197mmentovai int error = remove(path_.c_str()); 20550e299b00e803f085b34847dfe5232b471d84197mmentovai Release(); 20650e299b00e803f085b34847dfe5232b471d84197mmentovai return error; 20750e299b00e803f085b34847dfe5232b471d84197mmentovai } 20850e299b00e803f085b34847dfe5232b471d84197mmentovai 20950e299b00e803f085b34847dfe5232b471d84197mmentovai void Release() { 21050e299b00e803f085b34847dfe5232b471d84197mmentovai path_.clear(); 21150e299b00e803f085b34847dfe5232b471d84197mmentovai } 21250e299b00e803f085b34847dfe5232b471d84197mmentovai 21350e299b00e803f085b34847dfe5232b471d84197mmentovai private: 21450e299b00e803f085b34847dfe5232b471d84197mmentovai string path_; 21550e299b00e803f085b34847dfe5232b471d84197mmentovai}; 21650e299b00e803f085b34847dfe5232b471d84197mmentovai 21750e299b00e803f085b34847dfe5232b471d84197mmentovaiMSSymbolServerConverter::LocateResult 2180a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.comMSSymbolServerConverter::LocateFile(const string &debug_or_code_file, 2190a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com const string &debug_or_code_id, 2200a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com const string &version, 2210a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com string *file_name) { 2220a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com assert(file_name); 2230a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com file_name->clear(); 22450e299b00e803f085b34847dfe5232b471d84197mmentovai 22550e299b00e803f085b34847dfe5232b471d84197mmentovai GUIDOrSignatureIdentifier identifier; 2260a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com if (!identifier.InitializeFromString(debug_or_code_id)) { 22750e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, 2280a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "LocateFile: Unparseable identifier for %s %s %s\n", 2290a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_file.c_str(), 2300a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_id.c_str(), 2310a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com version.c_str()); 23250e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 23350e299b00e803f085b34847dfe5232b471d84197mmentovai } 23450e299b00e803f085b34847dfe5232b471d84197mmentovai 23550e299b00e803f085b34847dfe5232b471d84197mmentovai HANDLE process = GetCurrentProcess(); // CloseHandle is not needed. 23650e299b00e803f085b34847dfe5232b471d84197mmentovai AutoSymSrv symsrv; 23750e299b00e803f085b34847dfe5232b471d84197mmentovai if (!symsrv.Initialize(process, 23850e299b00e803f085b34847dfe5232b471d84197mmentovai const_cast<char *>(symbol_path_.c_str()), 23950e299b00e803f085b34847dfe5232b471d84197mmentovai false)) { 2400a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, "LocateFile: SymInitialize: error %d for %s %s %s\n", 24150e299b00e803f085b34847dfe5232b471d84197mmentovai GetLastError(), 2420a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_file.c_str(), 2430a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_id.c_str(), 2440a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com version.c_str()); 24550e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 24650e299b00e803f085b34847dfe5232b471d84197mmentovai } 24750e299b00e803f085b34847dfe5232b471d84197mmentovai 24850e299b00e803f085b34847dfe5232b471d84197mmentovai if (!SymRegisterCallback64(process, SymCallback, 24950e299b00e803f085b34847dfe5232b471d84197mmentovai reinterpret_cast<ULONG64>(this))) { 25050e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, 2510a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "LocateFile: SymRegisterCallback64: error %d for %s %s %s\n", 25250e299b00e803f085b34847dfe5232b471d84197mmentovai GetLastError(), 2530a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_file.c_str(), 2540a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_id.c_str(), 2550a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com version.c_str()); 25650e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 25750e299b00e803f085b34847dfe5232b471d84197mmentovai } 25850e299b00e803f085b34847dfe5232b471d84197mmentovai 25950e299b00e803f085b34847dfe5232b471d84197mmentovai // SYMOPT_DEBUG arranges for SymCallback to be called with additional 26050e299b00e803f085b34847dfe5232b471d84197mmentovai // debugging information. This is used to determine the nature of failures. 26150e299b00e803f085b34847dfe5232b471d84197mmentovai DWORD options = SymGetOptions() | SYMOPT_DEBUG | SYMOPT_NO_PROMPTS | 26250e299b00e803f085b34847dfe5232b471d84197mmentovai SYMOPT_FAIL_CRITICAL_ERRORS | SYMOPT_SECURE; 26350e299b00e803f085b34847dfe5232b471d84197mmentovai SymSetOptions(options); 26450e299b00e803f085b34847dfe5232b471d84197mmentovai 26550e299b00e803f085b34847dfe5232b471d84197mmentovai // SymCallback will set these as needed inisde the SymFindFileInPath call. 26650e299b00e803f085b34847dfe5232b471d84197mmentovai fail_dns_ = false; 26750e299b00e803f085b34847dfe5232b471d84197mmentovai fail_timeout_ = false; 26850e299b00e803f085b34847dfe5232b471d84197mmentovai fail_not_found_ = false; 26950e299b00e803f085b34847dfe5232b471d84197mmentovai 27050e299b00e803f085b34847dfe5232b471d84197mmentovai // Do the lookup. 27150e299b00e803f085b34847dfe5232b471d84197mmentovai char path[MAX_PATH]; 27250e299b00e803f085b34847dfe5232b471d84197mmentovai if (!SymFindFileInPath( 27350e299b00e803f085b34847dfe5232b471d84197mmentovai process, NULL, 2740a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com const_cast<char *>(debug_or_code_file.c_str()), 27550e299b00e803f085b34847dfe5232b471d84197mmentovai const_cast<void *>(identifier.guid_or_signature_pointer()), 27650e299b00e803f085b34847dfe5232b471d84197mmentovai identifier.age(), 0, 27750e299b00e803f085b34847dfe5232b471d84197mmentovai identifier.type() == GUIDOrSignatureIdentifier::TYPE_GUID ? 27850e299b00e803f085b34847dfe5232b471d84197mmentovai SSRVOPT_GUIDPTR : SSRVOPT_DWORDPTR, 27950e299b00e803f085b34847dfe5232b471d84197mmentovai path, SymFindFileInPathCallback, this)) { 28050e299b00e803f085b34847dfe5232b471d84197mmentovai DWORD error = GetLastError(); 28150e299b00e803f085b34847dfe5232b471d84197mmentovai if (error == ERROR_FILE_NOT_FOUND) { 28250e299b00e803f085b34847dfe5232b471d84197mmentovai // This can be returned for a number of reasons. Use the crumbs 28350e299b00e803f085b34847dfe5232b471d84197mmentovai // collected by SymCallback to determine which one is relevant. 28450e299b00e803f085b34847dfe5232b471d84197mmentovai 28550e299b00e803f085b34847dfe5232b471d84197mmentovai // These errors are possibly transient. 28650e299b00e803f085b34847dfe5232b471d84197mmentovai if (fail_dns_ || fail_timeout_) { 28750e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_RETRY; 28850e299b00e803f085b34847dfe5232b471d84197mmentovai } 28950e299b00e803f085b34847dfe5232b471d84197mmentovai 29050e299b00e803f085b34847dfe5232b471d84197mmentovai // This is an authoritiative file-not-found message. 29150e299b00e803f085b34847dfe5232b471d84197mmentovai if (fail_not_found_) { 29211dc02869471b92f6e11023477e9cfed9ff11cd0doshimun fprintf(stderr, 2930a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "LocateFile: SymFindFileInPath: LOCATE_NOT_FOUND error " 29411dc02869471b92f6e11023477e9cfed9ff11cd0doshimun "for %s %s %s\n", 2950a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_file.c_str(), 2960a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_id.c_str(), 2970a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com version.c_str()); 29850e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_NOT_FOUND; 29950e299b00e803f085b34847dfe5232b471d84197mmentovai } 30050e299b00e803f085b34847dfe5232b471d84197mmentovai 30150e299b00e803f085b34847dfe5232b471d84197mmentovai // If the error is FILE_NOT_FOUND but none of the known error 30250e299b00e803f085b34847dfe5232b471d84197mmentovai // conditions are matched, fall through to LOCATE_FAILURE. 30350e299b00e803f085b34847dfe5232b471d84197mmentovai } 30450e299b00e803f085b34847dfe5232b471d84197mmentovai 30550e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, 3060a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "LocateFile: SymFindFileInPath: error %d for %s %s %s\n", 30750e299b00e803f085b34847dfe5232b471d84197mmentovai error, 3080a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_file.c_str(), 3090a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_id.c_str(), 3100a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com version.c_str()); 31150e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 31250e299b00e803f085b34847dfe5232b471d84197mmentovai } 31350e299b00e803f085b34847dfe5232b471d84197mmentovai 3140a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com // Making sure path is null-terminated. 3150a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com path[MAX_PATH - 1] = '\0'; 3160a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 31750e299b00e803f085b34847dfe5232b471d84197mmentovai // The AutoDeleter ensures that the file is only kept when returning 31850e299b00e803f085b34847dfe5232b471d84197mmentovai // LOCATE_SUCCESS. 31950e299b00e803f085b34847dfe5232b471d84197mmentovai AutoDeleter deleter(path); 32050e299b00e803f085b34847dfe5232b471d84197mmentovai 32150e299b00e803f085b34847dfe5232b471d84197mmentovai // Do the cleanup here even though it will happen when symsrv goes out of 32250e299b00e803f085b34847dfe5232b471d84197mmentovai // scope, to allow it to influence the return value. 32350e299b00e803f085b34847dfe5232b471d84197mmentovai if (!symsrv.Cleanup()) { 3240a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, "LocateFile: SymCleanup: error %d for %s %s %s\n", 32550e299b00e803f085b34847dfe5232b471d84197mmentovai GetLastError(), 3260a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_file.c_str(), 3270a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com debug_or_code_id.c_str(), 3280a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com version.c_str()); 32950e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 33050e299b00e803f085b34847dfe5232b471d84197mmentovai } 33150e299b00e803f085b34847dfe5232b471d84197mmentovai 33250e299b00e803f085b34847dfe5232b471d84197mmentovai deleter.Release(); 33350e299b00e803f085b34847dfe5232b471d84197mmentovai 3340a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com printf("Downloaded: %s\n", path); 3350a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com *file_name = path; 33650e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_SUCCESS; 33750e299b00e803f085b34847dfe5232b471d84197mmentovai} 33850e299b00e803f085b34847dfe5232b471d84197mmentovai 3390a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 3400a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.comMSSymbolServerConverter::LocateResult 3410a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.comMSSymbolServerConverter::LocatePEFile(const MissingSymbolInfo &missing, 3420a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com string *pe_file) { 3430a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com return LocateFile(missing.code_file, missing.code_identifier, 3440a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com missing.version, pe_file); 3450a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com} 3460a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 3470a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.comMSSymbolServerConverter::LocateResult 3480a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.comMSSymbolServerConverter::LocateSymbolFile(const MissingSymbolInfo &missing, 3490a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com string *symbol_file) { 3500a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com return LocateFile(missing.debug_file, missing.debug_identifier, 3510a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com missing.version, symbol_file); 3520a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com} 3530a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 3540a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 35550e299b00e803f085b34847dfe5232b471d84197mmentovai// static 35650e299b00e803f085b34847dfe5232b471d84197mmentovaiBOOL CALLBACK MSSymbolServerConverter::SymCallback(HANDLE process, 35750e299b00e803f085b34847dfe5232b471d84197mmentovai ULONG action, 35850e299b00e803f085b34847dfe5232b471d84197mmentovai ULONG64 data, 35950e299b00e803f085b34847dfe5232b471d84197mmentovai ULONG64 context) { 36050e299b00e803f085b34847dfe5232b471d84197mmentovai MSSymbolServerConverter *self = 36150e299b00e803f085b34847dfe5232b471d84197mmentovai reinterpret_cast<MSSymbolServerConverter *>(context); 36250e299b00e803f085b34847dfe5232b471d84197mmentovai 36350e299b00e803f085b34847dfe5232b471d84197mmentovai switch (action) { 36450e299b00e803f085b34847dfe5232b471d84197mmentovai case CBA_EVENT: { 36550e299b00e803f085b34847dfe5232b471d84197mmentovai IMAGEHLP_CBA_EVENT *cba_event = 36650e299b00e803f085b34847dfe5232b471d84197mmentovai reinterpret_cast<IMAGEHLP_CBA_EVENT *>(data); 36750e299b00e803f085b34847dfe5232b471d84197mmentovai 3680a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com // Put the string into a string object to be able to use string::find 36950e299b00e803f085b34847dfe5232b471d84197mmentovai // for substring matching. This is important because the not-found 37050e299b00e803f085b34847dfe5232b471d84197mmentovai // message does not use the entire string but is appended to the URL 37150e299b00e803f085b34847dfe5232b471d84197mmentovai // that SymSrv attempted to retrieve. 37250e299b00e803f085b34847dfe5232b471d84197mmentovai string desc(cba_event->desc); 37350e299b00e803f085b34847dfe5232b471d84197mmentovai 37450e299b00e803f085b34847dfe5232b471d84197mmentovai // desc_action maps strings (in desc) to boolean pointers that are to 37550e299b00e803f085b34847dfe5232b471d84197mmentovai // be set to true if the string matches. 37650e299b00e803f085b34847dfe5232b471d84197mmentovai struct desc_action { 37750e299b00e803f085b34847dfe5232b471d84197mmentovai const char *desc; // The substring to match. 37850e299b00e803f085b34847dfe5232b471d84197mmentovai bool *action; // On match, this pointer will be set to true. 37950e299b00e803f085b34847dfe5232b471d84197mmentovai }; 38050e299b00e803f085b34847dfe5232b471d84197mmentovai 38150e299b00e803f085b34847dfe5232b471d84197mmentovai static const desc_action desc_actions[] = { 38250e299b00e803f085b34847dfe5232b471d84197mmentovai // When a DNS error occurs, it could be indiciative of network 38350e299b00e803f085b34847dfe5232b471d84197mmentovai // problems. 38450e299b00e803f085b34847dfe5232b471d84197mmentovai { "SYMSRV: The server name or address could not be resolved\n", 38550e299b00e803f085b34847dfe5232b471d84197mmentovai &self->fail_dns_ }, 38650e299b00e803f085b34847dfe5232b471d84197mmentovai 38750e299b00e803f085b34847dfe5232b471d84197mmentovai // This message is produced if no connection is opened. 38850e299b00e803f085b34847dfe5232b471d84197mmentovai { "SYMSRV: A connection with the server could not be established\n", 38950e299b00e803f085b34847dfe5232b471d84197mmentovai &self->fail_timeout_ }, 39050e299b00e803f085b34847dfe5232b471d84197mmentovai 39150e299b00e803f085b34847dfe5232b471d84197mmentovai // This message is produced if a connection is established but the 39250e299b00e803f085b34847dfe5232b471d84197mmentovai // server fails to respond to the HTTP request. 39350e299b00e803f085b34847dfe5232b471d84197mmentovai { "SYMSRV: The operation timed out\n", 39450e299b00e803f085b34847dfe5232b471d84197mmentovai &self->fail_timeout_ }, 39550e299b00e803f085b34847dfe5232b471d84197mmentovai 39650e299b00e803f085b34847dfe5232b471d84197mmentovai // This message is produced when the requested file is not found, 39750e299b00e803f085b34847dfe5232b471d84197mmentovai // even if one or more of the above messages are also produced. 39850e299b00e803f085b34847dfe5232b471d84197mmentovai // It's trapped to distinguish between not-found and unknown-failure 39950e299b00e803f085b34847dfe5232b471d84197mmentovai // conditions. Note that this message will not be produced if a 40050e299b00e803f085b34847dfe5232b471d84197mmentovai // connection is established and the server begins to respond to the 40150e299b00e803f085b34847dfe5232b471d84197mmentovai // HTTP request but does not finish transmitting the file. 40250e299b00e803f085b34847dfe5232b471d84197mmentovai { " not found\n", 40350e299b00e803f085b34847dfe5232b471d84197mmentovai &self->fail_not_found_ } 40450e299b00e803f085b34847dfe5232b471d84197mmentovai }; 40550e299b00e803f085b34847dfe5232b471d84197mmentovai 40650e299b00e803f085b34847dfe5232b471d84197mmentovai for (int desc_action_index = 0; 40750e299b00e803f085b34847dfe5232b471d84197mmentovai desc_action_index < sizeof(desc_actions) / sizeof(desc_action); 40850e299b00e803f085b34847dfe5232b471d84197mmentovai ++desc_action_index) { 40950e299b00e803f085b34847dfe5232b471d84197mmentovai if (desc.find(desc_actions[desc_action_index].desc) != string::npos) { 41050e299b00e803f085b34847dfe5232b471d84197mmentovai *(desc_actions[desc_action_index].action) = true; 41150e299b00e803f085b34847dfe5232b471d84197mmentovai break; 41250e299b00e803f085b34847dfe5232b471d84197mmentovai } 41350e299b00e803f085b34847dfe5232b471d84197mmentovai } 41450e299b00e803f085b34847dfe5232b471d84197mmentovai 41550e299b00e803f085b34847dfe5232b471d84197mmentovai break; 41650e299b00e803f085b34847dfe5232b471d84197mmentovai } 41750e299b00e803f085b34847dfe5232b471d84197mmentovai } 41850e299b00e803f085b34847dfe5232b471d84197mmentovai 41950e299b00e803f085b34847dfe5232b471d84197mmentovai // This function is a mere fly on the wall. Treat everything as unhandled. 42050e299b00e803f085b34847dfe5232b471d84197mmentovai return FALSE; 42150e299b00e803f085b34847dfe5232b471d84197mmentovai} 42250e299b00e803f085b34847dfe5232b471d84197mmentovai 42350e299b00e803f085b34847dfe5232b471d84197mmentovai// static 42450e299b00e803f085b34847dfe5232b471d84197mmentovaiBOOL CALLBACK MSSymbolServerConverter::SymFindFileInPathCallback( 4250a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com const char *filename, void *context) { 42650e299b00e803f085b34847dfe5232b471d84197mmentovai // FALSE ends the search, indicating that the located symbol file is 42750e299b00e803f085b34847dfe5232b471d84197mmentovai // satisfactory. 42850e299b00e803f085b34847dfe5232b471d84197mmentovai return FALSE; 42950e299b00e803f085b34847dfe5232b471d84197mmentovai} 43050e299b00e803f085b34847dfe5232b471d84197mmentovai 43150e299b00e803f085b34847dfe5232b471d84197mmentovaiMSSymbolServerConverter::LocateResult 43250e299b00e803f085b34847dfe5232b471d84197mmentovaiMSSymbolServerConverter::LocateAndConvertSymbolFile( 43350e299b00e803f085b34847dfe5232b471d84197mmentovai const MissingSymbolInfo &missing, 43450e299b00e803f085b34847dfe5232b471d84197mmentovai bool keep_symbol_file, 4350a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com bool keep_pe_file, 43650e299b00e803f085b34847dfe5232b471d84197mmentovai string *converted_symbol_file, 4370a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com string *symbol_file, 4380a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com string *out_pe_file) { 43950e299b00e803f085b34847dfe5232b471d84197mmentovai assert(converted_symbol_file); 44050e299b00e803f085b34847dfe5232b471d84197mmentovai converted_symbol_file->clear(); 44150e299b00e803f085b34847dfe5232b471d84197mmentovai if (symbol_file) { 44250e299b00e803f085b34847dfe5232b471d84197mmentovai symbol_file->clear(); 44350e299b00e803f085b34847dfe5232b471d84197mmentovai } 44450e299b00e803f085b34847dfe5232b471d84197mmentovai 44550e299b00e803f085b34847dfe5232b471d84197mmentovai string pdb_file; 44650e299b00e803f085b34847dfe5232b471d84197mmentovai LocateResult result = LocateSymbolFile(missing, &pdb_file); 44750e299b00e803f085b34847dfe5232b471d84197mmentovai if (result != LOCATE_SUCCESS) { 44850e299b00e803f085b34847dfe5232b471d84197mmentovai return result; 44950e299b00e803f085b34847dfe5232b471d84197mmentovai } 45050e299b00e803f085b34847dfe5232b471d84197mmentovai 45150e299b00e803f085b34847dfe5232b471d84197mmentovai if (symbol_file && keep_symbol_file) { 45250e299b00e803f085b34847dfe5232b471d84197mmentovai *symbol_file = pdb_file; 45350e299b00e803f085b34847dfe5232b471d84197mmentovai } 45450e299b00e803f085b34847dfe5232b471d84197mmentovai 4550a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com // The conversion of a symbol file for a Windows 64-bit module requires 4560a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com // loading of the executable file. If there is no executable file, convert 4570a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com // using only the PDB file. Without an executable file, the conversion will 4580a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com // fail for 64-bit modules but it should succeed for 32-bit modules. 4590a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com string pe_file; 4600a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com result = LocatePEFile(missing, &pe_file); 4610a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com if (result != LOCATE_SUCCESS) { 4620a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, "WARNING: Could not download: %s\n", pe_file.c_str()); 4630a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com } 4640a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 4650a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com if (out_pe_file && keep_pe_file) { 4660a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com *out_pe_file = pe_file; 4670a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com } 4680a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 46950e299b00e803f085b34847dfe5232b471d84197mmentovai // Conversion may fail because the file is corrupt. If a broken file is 47050e299b00e803f085b34847dfe5232b471d84197mmentovai // kept in the local cache, LocateSymbolFile will not hit the network again 47150e299b00e803f085b34847dfe5232b471d84197mmentovai // to attempt to locate it. To guard against problems like this, the 47250e299b00e803f085b34847dfe5232b471d84197mmentovai // symbol file in the local cache will be removed if conversion fails. 47350e299b00e803f085b34847dfe5232b471d84197mmentovai AutoDeleter pdb_deleter(pdb_file); 4740a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com AutoDeleter pe_deleter(pe_file); 47550e299b00e803f085b34847dfe5232b471d84197mmentovai 47650e299b00e803f085b34847dfe5232b471d84197mmentovai // Be sure that it's a .pdb file, since we'll be replacing .pdb with .sym 47750e299b00e803f085b34847dfe5232b471d84197mmentovai // for the converted file's name. 47850e299b00e803f085b34847dfe5232b471d84197mmentovai string pdb_extension = pdb_file.substr(pdb_file.length() - 4); 47950e299b00e803f085b34847dfe5232b471d84197mmentovai // strcasecmp is called _stricmp here. 48050e299b00e803f085b34847dfe5232b471d84197mmentovai if (_stricmp(pdb_extension.c_str(), ".pdb") != 0) { 48150e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, "LocateAndConvertSymbolFile: " 4820a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "no .pdb extension for %s %s %s %s\n", 48350e299b00e803f085b34847dfe5232b471d84197mmentovai missing.debug_file.c_str(), 48450e299b00e803f085b34847dfe5232b471d84197mmentovai missing.debug_identifier.c_str(), 48550e299b00e803f085b34847dfe5232b471d84197mmentovai missing.version.c_str(), 48650e299b00e803f085b34847dfe5232b471d84197mmentovai pdb_file.c_str()); 48750e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 48850e299b00e803f085b34847dfe5232b471d84197mmentovai } 48950e299b00e803f085b34847dfe5232b471d84197mmentovai 4900a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com PDBSourceLineWriter writer; 4910a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com wstring pe_file_w; 4920a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com if (!WindowsStringUtils::safe_mbstowcs(pe_file, &pe_file_w)) { 4930a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, 4940a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "LocateAndConvertSymbolFile: " 4950a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "WindowsStringUtils::safe_mbstowcs failed for %s\n", 4960a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com pe_file.c_str()); 4970a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com return LOCATE_FAILURE; 4980a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com } 49950e299b00e803f085b34847dfe5232b471d84197mmentovai wstring pdb_file_w; 50050e299b00e803f085b34847dfe5232b471d84197mmentovai if (!WindowsStringUtils::safe_mbstowcs(pdb_file, &pdb_file_w)) { 5010a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, 5020a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "LocateAndConvertSymbolFile: " 5030a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "WindowsStringUtils::safe_mbstowcs failed for %s\n", 5040a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com pdb_file_w.c_str()); 50550e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 50650e299b00e803f085b34847dfe5232b471d84197mmentovai } 50750e299b00e803f085b34847dfe5232b471d84197mmentovai if (!writer.Open(pdb_file_w, PDBSourceLineWriter::PDB_FILE)) { 5080a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, 5090a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "ERROR: PDBSourceLineWriter::Open failed for %s %s %s %ws\n", 5100a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com missing.debug_file.c_str(), missing.debug_identifier.c_str(), 5110a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com missing.version.c_str(), pdb_file_w.c_str()); 5120a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com return LOCATE_FAILURE; 5130a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com } 5140a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com if (!writer.SetCodeFile(pe_file_w)) { 5150a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com fprintf(stderr, 5160a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com "ERROR: PDBSourceLineWriter::SetCodeFile failed for %s %s %s %ws\n", 5170a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com missing.debug_file.c_str(), missing.debug_identifier.c_str(), 5180a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com missing.version.c_str(), pe_file_w.c_str()); 51950e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 52050e299b00e803f085b34847dfe5232b471d84197mmentovai } 52150e299b00e803f085b34847dfe5232b471d84197mmentovai 52250e299b00e803f085b34847dfe5232b471d84197mmentovai *converted_symbol_file = pdb_file.substr(0, pdb_file.length() - 4) + ".sym"; 52350e299b00e803f085b34847dfe5232b471d84197mmentovai 52450e299b00e803f085b34847dfe5232b471d84197mmentovai FILE *converted_output = NULL; 52550e299b00e803f085b34847dfe5232b471d84197mmentovai#if _MSC_VER >= 1400 // MSVC 2005/8 52650e299b00e803f085b34847dfe5232b471d84197mmentovai errno_t err; 52750e299b00e803f085b34847dfe5232b471d84197mmentovai if ((err = fopen_s(&converted_output, converted_symbol_file->c_str(), "w")) 52850e299b00e803f085b34847dfe5232b471d84197mmentovai != 0) { 52950e299b00e803f085b34847dfe5232b471d84197mmentovai#else // _MSC_VER >= 1400 53050e299b00e803f085b34847dfe5232b471d84197mmentovai // fopen_s and errno_t were introduced in MSVC8. Use fopen for earlier 53150e299b00e803f085b34847dfe5232b471d84197mmentovai // environments. Don't use fopen with MSVC8 and later, because it's 53250e299b00e803f085b34847dfe5232b471d84197mmentovai // deprecated. fopen does not provide reliable error codes, so just use 53350e299b00e803f085b34847dfe5232b471d84197mmentovai // -1 in the event of a failure. 53450e299b00e803f085b34847dfe5232b471d84197mmentovai int err; 53550e299b00e803f085b34847dfe5232b471d84197mmentovai if (!(converted_output = fopen(converted_symbol_file->c_str(), "w"))) { 53650e299b00e803f085b34847dfe5232b471d84197mmentovai err = -1; 53750e299b00e803f085b34847dfe5232b471d84197mmentovai#endif // _MSC_VER >= 1400 53850e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, "LocateAndConvertSymbolFile: " 53950e299b00e803f085b34847dfe5232b471d84197mmentovai "fopen_s: error %d for %s %s %s %s\n", 54050e299b00e803f085b34847dfe5232b471d84197mmentovai err, 54150e299b00e803f085b34847dfe5232b471d84197mmentovai missing.debug_file.c_str(), 54250e299b00e803f085b34847dfe5232b471d84197mmentovai missing.debug_identifier.c_str(), 54350e299b00e803f085b34847dfe5232b471d84197mmentovai missing.version.c_str(), 54450e299b00e803f085b34847dfe5232b471d84197mmentovai converted_symbol_file->c_str()); 54550e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 54650e299b00e803f085b34847dfe5232b471d84197mmentovai } 54750e299b00e803f085b34847dfe5232b471d84197mmentovai 54850e299b00e803f085b34847dfe5232b471d84197mmentovai AutoDeleter sym_deleter(*converted_symbol_file); 54950e299b00e803f085b34847dfe5232b471d84197mmentovai 55050e299b00e803f085b34847dfe5232b471d84197mmentovai bool success = writer.WriteMap(converted_output); 55150e299b00e803f085b34847dfe5232b471d84197mmentovai fclose(converted_output); 55250e299b00e803f085b34847dfe5232b471d84197mmentovai 55350e299b00e803f085b34847dfe5232b471d84197mmentovai if (!success) { 55450e299b00e803f085b34847dfe5232b471d84197mmentovai fprintf(stderr, "LocateAndConvertSymbolFile: " 55550e299b00e803f085b34847dfe5232b471d84197mmentovai "PDBSourceLineWriter::WriteMap failed for %s %s %s %s\n", 55650e299b00e803f085b34847dfe5232b471d84197mmentovai missing.debug_file.c_str(), 55750e299b00e803f085b34847dfe5232b471d84197mmentovai missing.debug_identifier.c_str(), 55850e299b00e803f085b34847dfe5232b471d84197mmentovai missing.version.c_str(), 55950e299b00e803f085b34847dfe5232b471d84197mmentovai pdb_file.c_str()); 56050e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_FAILURE; 56150e299b00e803f085b34847dfe5232b471d84197mmentovai } 56250e299b00e803f085b34847dfe5232b471d84197mmentovai 56350e299b00e803f085b34847dfe5232b471d84197mmentovai if (keep_symbol_file) { 56450e299b00e803f085b34847dfe5232b471d84197mmentovai pdb_deleter.Release(); 56550e299b00e803f085b34847dfe5232b471d84197mmentovai } 56650e299b00e803f085b34847dfe5232b471d84197mmentovai 5670a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com if (keep_pe_file) { 5680a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com pe_deleter.Release(); 5690a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com } 5700a35290a4ecafc23215c2df491f7093f18fcda97ivan.penkov@gmail.com 57150e299b00e803f085b34847dfe5232b471d84197mmentovai sym_deleter.Release(); 57250e299b00e803f085b34847dfe5232b471d84197mmentovai 57350e299b00e803f085b34847dfe5232b471d84197mmentovai return LOCATE_SUCCESS; 57450e299b00e803f085b34847dfe5232b471d84197mmentovai} 57550e299b00e803f085b34847dfe5232b471d84197mmentovai 576e5dc60822e5938fea2ae892ccddb906641ba174emmentovai} // namespace google_breakpad 577