// Copyright (c) 2007, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ms_symbol_server_converter.h: Obtain symbol files from a Microsoft // symbol server, and convert them to Breakpad's dumped format. // // At runtime, MSSymbolServerConverter and code that it calls depend on being // able to locate suitable versions of dbghelp.dll and symsrv.dll. For best // results, place these files in the same directory as the executable. // dbghelp.dll and symsrv.dll as supplied with Debugging Tools for Windows are // both redistributable, as indicated by the package's redist.txt file. // // When connecting to Microsoft's symbol server at // http://msdl.microsoft.com/download/symbols/, which provides access to // symbols for the operating system itself, symsrv.dll requires agreement to // Microsoft's "Terms of Use for Microsoft Symbols and Binaries." Because this // library places the symbol engine into a promptless mode, the dialog with the // terms will not appear, and use of Microsoft's symbol server will not be // possible. To indicate agreement to the terms, create a file called // symsrv.yes in the same directory as symsrv.dll. (Note that symsrv.dll will // also recognize a symsrv.no file as indicating that you do not accept the // terms; the .yes file takes priority over the .no file.) The terms of use // are contained within symsrv.dll; they were formerly available online at // http://www.microsoft.com/whdc/devtools/debugging/symsrvTOU2.mspx , but // do not appear to be available online any longer as of January, 2007. It is // possible to view the terms from within WinDbg (Debugging Tools for Windows) // by removing any symsrv.yes and symsrv.no files from WinDbg's directory, // setting the symbol path to include Microsoft's symbol server (.sympath), and // attempting to load symbols from their server (.reload). // // This code has been tested with dbghelp.dll 6.5.3.7 and symsrv.dll 6.5.3.8, // included with Microsoft Visual Studio 8 in Common7/IDE. This has also been // tested with dbghelp.dll and symsrv.dll versions 6.6.7.5 and 6.12.2.633, // included with the same versions of Debugging Tools for Windows, available at // http://www.microsoft.com/whdc/devtools/debugging/ . // // Author: Mark Mentovai #ifndef TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_ #define TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_ #include #include #include namespace google_breakpad { using std::string; using std::vector; // MissingSymbolInfo contains the subset of the information in the processor's // CodeModule structure relevant to obtaining a missing symbol file. Only // debug_file and debug_identifier are relevant in actually obtaining the // missing file; the other fields are for convenience. struct MissingSymbolInfo { string code_file; string code_identifier; string debug_file; string debug_identifier; string version; }; class GUIDOrSignatureIdentifier { public: enum GUIDOrSignatureType { TYPE_NONE = 0, TYPE_GUID, TYPE_SIGNATURE }; GUIDOrSignatureIdentifier() : type_(TYPE_NONE) {} // Converts |identifier|, a debug_identifier-formatted string, into its // component fields: either a GUID and age, or signature and age. If // successful, sets the relevant fields in the object, including the type // field, and returns true. On error, returns false. bool InitializeFromString(const string &identifier); GUIDOrSignatureType type() const { return type_; } GUID guid() const { return guid_; } DWORD signature() const { return signature_; } int age() const { return age_; } const void *guid_or_signature_pointer() const { return &guid_; } private: GUIDOrSignatureType type_; // An identifier contains either a 128-bit uuid or a 32-bit signature. union { GUID guid_; DWORD signature_; }; // All identifiers used here have age fields, which indicate a specific // revision given a uuid or signature. int age_; }; class MSSymbolServerConverter { public: enum LocateResult { LOCATE_FAILURE = 0, LOCATE_NOT_FOUND, // Authoritative: the file is not present. LOCATE_RETRY, // Transient (network?) error, try again later. LOCATE_SUCCESS }; // Create a new object. local_cache is the location (pathname) of a local // symbol store used to hold downloaded and converted symbol files. This // directory will be created by LocateSymbolFile when it successfully // retrieves a symbol file. symbol_servers contains a list of locations (URLs // or pathnames) of the upstream symbol server stores, given in order of // preference, with the first string in the vector identifying the first // store to try. The vector must contain at least one string. None of the // strings passed to this constructor may contain asterisk ('*') or semicolon // (';') characters, as the symbol engine uses these characters as separators. MSSymbolServerConverter(const string &local_cache, const vector &symbol_servers); // Locates the PE file (DLL or EXE) specified by the identifying information // in |missing|, by checking the symbol stores identified when the object // was created. When returning LOCATE_SUCCESS, pe_file is set to // the pathname of the decompressed PE file as it is stored in the // local cache. LocateResult LocatePEFile(const MissingSymbolInfo &missing, string *pe_file); // Locates the symbol file specified by the identifying information in // |missing|, by checking the symbol stores identified when the object // was created. When returning LOCATE_SUCCESS, symbol_file is set to // the pathname of the decompressed symbol file as it is stored in the // local cache. LocateResult LocateSymbolFile(const MissingSymbolInfo &missing, string *symbol_file); // Calls LocateSymbolFile and converts the returned symbol file to the // dumped-symbol format, storing it adjacent to the symbol file. The // only conversion supported is from pdb files. Returns the return // value of LocateSymbolFile, or if LocateSymbolFile succeeds but // conversion fails, returns LOCATE_FAILURE. The pathname to the // pdb file and to the converted symbol file are returned in // |converted_symbol_file|, |symbol_file|, and |pe_file|. |symbol_file| and // |pe_file| are optional and may be NULL. If only the converted symbol file // is desired, set |keep_symbol_file| and |keep_pe_file| to false to indicate // that the original symbol file (pdb) and executable file (exe, dll) should // be deleted after conversion. LocateResult LocateAndConvertSymbolFile(const MissingSymbolInfo &missing, bool keep_symbol_file, bool keep_pe_file, string *converted_symbol_file, string *symbol_file, string *pe_file); // Calls LocatePEFile and converts the returned PE file to the // dumped-symbol format, storing it adjacent to the PE file. The // only conversion supported is from PE files. Returns the return // value of LocatePEFile, or if LocatePEFile succeeds but // conversion fails, returns LOCATE_FAILURE. The pathname to the // PE file and to the converted symbol file are returned in // |converted_symbol_file| and |pe_file|. |pe_file| is optional and may be // NULL. If only the converted symbol file is desired, set |keep_pe_file| // to false to indicate that the executable file (exe, dll) should be deleted // after conversion. // NOTE: Currrently only supports x64 PEs. LocateResult LocateAndConvertPEFile(const MissingSymbolInfo &missing, bool keep_pe_file, string *converted_symbol_file, string *pe_file); private: // Locates the PDB or PE file (DLL or EXE) specified by the identifying // information in |debug_or_code_file| and |debug_or_code_id|, by checking // the symbol stores identified when the object was created. When // returning LOCATE_SUCCESS, file_name is set to the pathname of the // decompressed PDB or PE file file as it is stored in the local cache. LocateResult LocateFile(const string &debug_or_code_file, const string &debug_or_code_id, const string &version, string *file_name); // Called by various SymSrv functions to report status as progress is made // and to allow the callback to influence processing. Messages sent to this // callback can be used to distinguish between the various failure modes // that SymFindFileInPath might encounter. static BOOL CALLBACK SymCallback(HANDLE process, ULONG action, ULONG64 data, ULONG64 context); // Called by SymFindFileInPath (in LocateSymbolFile) after a candidate // symbol file is located, when it's present in the local cache. // SymFindFileInPath actually seems to accept NULL for a callback function // and behave properly for our needs in that case, but the documentation // doesn't mention it, so this little callback is provided. static BOOL CALLBACK SymFindFileInPathCallback(const char *filename, void *context); // The search path used by SymSrv, built based on the arguments to the // constructor. string symbol_path_; // SymCallback will set at least one of these failure variables if // SymFindFileInPath fails for an expected reason. bool fail_dns_; // DNS failures (fail_not_found_ will also be set). bool fail_timeout_; // Timeouts (fail_not_found_ will also be set). bool fail_not_found_; // The file could not be found. If this is the only // fail_* member set, then it is authoritative. }; } // namespace google_breakpad #endif // TOOLS_WINDOWS_MS_SYMBOL_SERVER_CONVERTER_H_