Home | History | Annotate | Download | only in converter
      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 
     73 namespace google_breakpad {
     74 
     75 using std::string;
     76 using 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.
     82 struct MissingSymbolInfo {
     83   string code_file;
     84   string code_identifier;
     85   string debug_file;
     86   string debug_identifier;
     87   string version;
     88 };
     89 
     90 class 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 
    126 class 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