• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
GUIDOrSignatureIdentifier()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  
type()106    GUIDOrSignatureType type() const { return type_; }
guid()107    GUID guid() const { return guid_; }
signature()108    DWORD signature() const { return signature_; }
age()109    int age() const { return age_; }
guid_or_signature_pointer()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