1// Copyright (c) 2007, Google Inc. 2// All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions are 6// met: 7// 8// * Redistributions of source code must retain the above copyright 9// notice, this list of conditions and the following disclaimer. 10// * Redistributions in binary form must reproduce the above 11// copyright notice, this list of conditions and the following disclaimer 12// in the documentation and/or other materials provided with the 13// distribution. 14// * Neither the name of Google Inc. nor the names of its 15// contributors may be used to endorse or promote products derived from 16// this software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30// ms_symbol_server_converter.h: Obtain symbol files from a Microsoft 31// symbol server, and convert them to Breakpad's dumped format. 32// 33// At runtime, MSSymbolServerConverter and code that it calls depend on being 34// able to locate suitable versions of dbghelp.dll and symsrv.dll. For best 35// results, place these files in the same directory as the executable. 36// dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are 37// both redistributable, as indicated by the package's redist.txt file. 38// 39// When connecting to Microsoft's symbol server at 40// http://msdl.microsoft.com/download/symbols/, which provides access to 41// symbols for the operating system itself, symsrv.dll requires agreement to 42// Microsoft's "Terms of Use for Microsoft Symbols and Binaries." Because this 43// library places the symbol engine into a promptless mode, the dialog with the 44// terms will not appear, and use of Microsoft's symbol server will not be 45// possible. To indicate agreement to the terms, create a file called 46// symsrv.yes in the same directory as symsrv.dll. (Note that symsrv.dll will 47// also recognize a symsrv.no file as indicating that you do not accept the 48// terms; the .yes file takes priority over the .no file.) The terms of use 49// are contained within symsrv.dll; they were formerly available online at 50// http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but 51// do not appear to be available online any longer as of January, 2007. It is 52// possible to view the terms from within WinDbg (Debugging Tools for Windows) 53// by removing any symsrv.yes and symsrv.no files from WinDbg's directory, 54// setting the symbol path to include Microsoft's symbol server (.sympath), and 55// attempting to load symbols from their server (.reload). 56// 57// This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8, 58// included with Microsoft Visual Studio 8 in Common7/IDE. This has also been 59// tested with dbghelp.dll and symsrv.dll versions 6.6.7.5 and 6.12.2.633, 60// included with the same versions of Debugging Tools for Windows, available at 61// http://www.microsoft.com/whdc/devtools/debugging/ . 62// 63// Author: Mark Mentovai 64 65#ifndef TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_ 66#define TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_ 67 68#include <windows.h> 69 70#include <string> 71#include <vector> 72 73namespace google_breakpad { 74 75using std::string; 76using std::vector; 77 78// MissingSymbolInfo contains the subset of the information in the processor's 79// CodeModule structure relevant to obtaining a missing symbol file. Only 80// debug_file and debug_identifier are relevant in actually obtaining the 81// missing file; the other fields are for convenience. 82struct MissingSymbolInfo { 83 string code_file; 84 string code_identifier; 85 string debug_file; 86 string debug_identifier; 87 string version; 88}; 89 90class GUIDOrSignatureIdentifier { 91 public: 92 enum GUIDOrSignatureType { 93 TYPE_NONE = 0, 94 TYPE_GUID, 95 TYPE_SIGNATURE 96 }; 97 98 GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {} 99 100 // Converts |identifier|, a debug_identifier-formatted string, into its 101 // component fields: either a GUID and age, or signature and age. If 102 // successful, sets the relevant fields in the object, including the type 103 // field, and returns true. On error, returns false. 104 bool InitializeFromString(const string &identifier); 105 106 GUIDOrSignatureType type() const { return type_; } 107 GUID guid() const { return guid_; } 108 DWORD signature() const { return signature_; } 109 int age() const { return age_; } 110 const void *guid_or_signature_pointer() const { return &guid_; } 111 112 private: 113 GUIDOrSignatureType type_; 114 115 // An identifier contains either a 128-bit uuid or a 32-bit signature. 116 union { 117 GUID guid_; 118 DWORD signature_; 119 }; 120 121 // All identifiers used here have age fields, which indicate a specific 122 // revision given a uuid or signature. 123 int age_; 124}; 125 126class MSSymbolServerConverter { 127 public: 128 enum LocateResult { 129 LOCATE_FAILURE = 0, 130 LOCATE_NOT_FOUND, // Authoritative: the file is not present. 131 LOCATE_RETRY, // Transient (network?) error, try again later. 132 LOCATE_SUCCESS 133 }; 134 135 // Create a new object. local_cache is the location (pathname) of a local 136 // symbol store used to hold downloaded and converted symbol files. This 137 // directory will be created by LocateSymbolFile when it successfully 138 // retrieves a symbol file. symbol_servers contains a list of locations (URLs 139 // or pathnames) of the upstream symbol server stores, given in order of 140 // preference, with the first string in the vector identifying the first 141 // store to try. The vector must contain at least one string. None of the 142 // strings passed to this constructor may contain asterisk ('*') or semicolon 143 // (';') characters, as the symbol engine uses these characters as separators. 144 MSSymbolServerConverter(const string &local_cache, 145 const vector<string> &symbol_servers); 146 147 // Locates the PE file (DLL or EXE) specified by the identifying information 148 // in |missing|, by checking the symbol stores identified when the object 149 // was created. When returning LOCATE_SUCCESS, pe_file is set to 150 // the pathname of the decompressed PE file as it is stored in the 151 // local cache. 152 LocateResult LocatePEFile(const MissingSymbolInfo &missing, string *pe_file); 153 154 // Locates the symbol file specified by the identifying information in 155 // |missing|, by checking the symbol stores identified when the object 156 // was created. When returning LOCATE_SUCCESS, symbol_file is set to 157 // the pathname of the decompressed symbol file as it is stored in the 158 // local cache. 159 LocateResult LocateSymbolFile(const MissingSymbolInfo &missing, 160 string *symbol_file); 161 162 // Calls LocateSymbolFile and converts the returned symbol file to the 163 // dumped-symbol format, storing it adjacent to the symbol file. The 164 // only conversion supported is from pdb files. Returns the return 165 // value of LocateSymbolFile, or if LocateSymbolFile succeeds but 166 // conversion fails, returns LOCATE_FAILURE. The pathname to the 167 // pdb file and to the converted symbol file are returned in 168 // |converted_symbol_file|, |symbol_file|, and |pe_file|. |symbol_file| and 169 // |pe_file| are optional and may be NULL. If only the converted symbol file 170 // is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate 171 // that the original symbol file (pdb) and executable file (exe, dll) should 172 // be deleted after conversion. 173 LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo &missing, 174 bool keep_symbol_file, 175 bool keep_pe_file, 176 string *converted_symbol_file, 177 string *symbol_file, 178 string *pe_file); 179 180 private: 181 // Locates the PDB or PE file (DLL or EXE) specified by the identifying 182 // information in |debug_or_code_file| and |debug_or_code_id|, by checking 183 // the symbol stores identified when the object was created. When 184 // returning LOCATE_SUCCESS, file_name is set to the pathname of the 185 // decompressed PDB or PE file file as it is stored in the local cache. 186 LocateResult LocateFile(const string &debug_or_code_file, 187 const string &debug_or_code_id, 188 const string &version, string *file_name); 189 190 // Called by various SymSrv functions to report status as progress is made 191 // and to allow the callback to influence processing. Messages sent to this 192 // callback can be used to distinguish between the various failure modes 193 // that SymFindFileInPath might encounter. 194 static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data, 195 ULONG64 context); 196 197 // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate 198 // symbol file is located, when it's present in the local cache. 199 // SymFindFileInPath actually seems to accept NULL for a callback function 200 // and behave properly for our needs in that case, but the documentation 201 // doesn't mention it, so this little callback is provided. 202 static BOOL CALLBACK SymFindFileInPathCallback(const char *filename, 203 void *context); 204 205 // The search path used by SymSrv, built based on the arguments to the 206 // constructor. 207 string symbol_path_; 208 209 // SymCallback will set at least one of these failure variables if 210 // SymFindFileInPath fails for an expected reason. 211 bool fail_dns_; // DNS failures (fail_not_found_ will also be set). 212 bool fail_timeout_; // Timeouts (fail_not_found_ will also be set). 213 bool fail_not_found_; // The file could not be found. If this is the only 214 // fail_* member set, then it is authoritative. 215}; 216 217} // namespace google_breakpad 218 219#endif // TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_ 220