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